Выбрать главу
ин терфейс IDictionary IEnumerable Определяет метод GetEnumerator(), предоставляющий перечислитель для любого класса коллекции IEnumerator Предоставляет методы, позволяющие получать содержимое коллекции по очереди IEqualityComparer Сравнивает два объекта на предмет равенства IHashCodeProvider Считается устаревшим. Вместо него следует использовать ин терфейс IEqualityComparer IList Определяет коллекцию, доступ к которой можно получить с по мощью индексатора IStructuralComparable Определяет метод CompareTo(), применяемый для струк турного сравнения IStructuralEquatable Определяет метод Equals(), применяемый для выяснения структурного, а не ссылочного равенства. Кроме того, опреде ляет метод GetHashCode() Метод СоруТо() копирует содержимое коллекции в массив target, начиная с эле мента, указываемого по индексу startIdx. Следовательно, метод СоруТо() обеспечи вает в C# переход от коллекции к стандартному массиву. Благодаря тому что интерфейс ICollection наследует от интерфейса IEnumerable, в его состав входит также единственный метод, определенный в интерфейсе IEnumerable. Это метод GetEnumerator(), объявляемый следующим образом. IEnumerator GetEnumerator() Он возвращает перечислитель для коллекции. Вследствие того же наследования от интерфейса IEnumerable в интерфей се ICollection определяются также четыре следующих метода расширения: AsParallel(), AsQueryable(), Cast() и OfType(). В частности, метод AsParallel() объявляется в классе System.Linq.ParallelEnumerable, метод AsQueryable() — в классе System.Linq.Queryable, а методы Cast() и OfType() — в классе System. Linq.Enumerable. Эти методы предназначены главным образом для поддержки LINQ, хотя их можно применять и в других целях. Интерфейс IList В интерфейсе IList объявляется такое поведение необобщенной коллекции, ко торое позволяет осуществлять доступ к ее элементам по индексу с отсчетом от нуля. Этот интерфейс наследует от интерфейсов ICollection и IEnumerable. Помимо методов, определенных в этих интерфейсах, в интерфейсе IList определяется ряд собственных методов. Все эти методы сведены в табл. 25.2. В некоторых из них преду сматривается модификация коллекции. Если же коллекция доступна только для чте ния или имеет фиксированный размер, то в этих методах генерируется исключение NotSupportedException. Таблица 25.2. Методы, определенные в интерфейсе IList Свойство Назначение int Count { get; } Содержит количество элементов в коллекции на дан ный момент bool IsSynchronized { get; } Принимает логическое значение true, если коллек ция синхронизирована, а иначе — логическое зна чение false. По умолчанию коллекции не синхро низированы. Но для большинства коллекций можно получить синхронизированный вариант object SyncRoot { get; } Содержит объект, для которого коллекция может быть синхронизирована Метод Описание int Add(object value) Добавляет объект value в вызывающую коллекцию. Возвращает индекс, по которому этот объект сохра няется void Clear() Удаляет все элементы из вызывающей коллекции bool Contains (object value) Возвращает логическое значение true, если вызы вающая коллекция содержит объект value, а ина че — логическое значение false Окончание табл. 25.2 Объекты добавляются в коллекцию типа IList вызовом метода Add(). Обрати те внимание на то, что метод Add() принимает аргумент типа object. А поскольку object является базовым классом для всех типов, то в необобщенной коллекции мо жет быть сохранен объект любого типа, включая и типы значений, в силу автоматиче ской упаковки и распаковки. Для удаления элемента из коллекции служат методы Remove() и RemoveAt(). В част ности, метод Remove() удаляет указанный объект, а метод RemoveAt() удаляет объект по указанному индексу. И для опорожнения коллекции вызывается метод Clear(). Для того чтобы выяснить, содержится ли в коллекции конкретный объект, вызыва ется метод Contains(). Для получения индекса объекта вызывается метод IndexOf(), а для вставки элемента в коллекцию по указанному индексу — метод Insert(). В интерфейсе IList определяются следующие свойства. bool IsFixedSize { get; } bool IsReadOnly { get; } Если коллекция имеет фиксированный размер, то свойство IsFixedSize содержит логическое значение true. Это означает, что в такую коллекцию нельзя ни вставлять элементы, ни удалять их из нее. Если же коллекция доступна только для чтения, то свойство IsReadOnly содержит логическое значение true. Это означает, что содержи мое такой коллекции не подлежит изменению. Кроме того, в интерфейсе IList определяется следующий индексатор. object this[int index] { get; set; } Этот индексатор служит для получения и установки значения элемента коллекции. Но его нельзя использовать для добавления в коллекцию нового элемента. С этой це лью обычно вызывается метод Add(). Как только элемент будет добавлен в коллекцию, он станет доступным посредством индексатора. Метод Описание int IndexOf(object value) Возвращает индекс объекта value, если этот объект содержится в вызывающей коллекции. Если же объект value не обнаружен, то метод возвращает значение -1 void Insert(int index, object value) Вставляет в вызывающую коллекцию объект value по индексу index. Элементы, находившиеся до это го по индексу index и дальше, смещаются вперед, чтобы освободить место для вставляемого объекта value void Remove(object value) Удаляет первое вхождение объекта value в вызыва ющей коллекции. Элементы, находившиеся до этого за удаленным элементом, смещаются назад, чтобы устранить образовавшийся “пробел" void RemoveAt(int index) Удаляет из вызывающей коллекции объект, располо женный по указанному индексу index. Элементы, находившиеся до этого за удаленным элементом, смещаются назад, чтобы устранить образовавшийся “пробел” Интерфейс IDictionary В интерфейсе IDictionary определяется такое поведение необобщенной кол лекции, которое позволяет преобразовать уникальные ключи в соответствующие зна чения. Ключ представляет собой объект, с помощью которого значение извлекается впоследствии. Следовательно, в коллекции, реализующей интерфейс IDictionary, хранятся пары "ключ-значение". Как только подобная пара будет сохранена, ее мож но извлечь с помощью ключа. Интерфейс IDictionary наследует от интерфейсов ICollection и IEnumerable. Методы, объявленные в интерфейсе IDictionary, све дены в табл. 25.3. Некоторые из них генерируют исключение ArgumentNullException при попытке указать пустой ключ, поскольку пустые ключи не допускаются. Таблица 25.3. Методы, определенные в интерфейсе IDictionary Для добавления пары "ключ-значение" в коллекцию типа IDictionary служит метод Add(). Обратите внимание на то, что ключ и его значение указываются отдель но. А для удаления элемента из коллекции следует указать ключ этого объекта при вызове метода Remove(). И для опорожнения коллекции вызывается метод Clear(). Для того чтобы выяснить, содержит ли коллекция конкретный объект, вызыва ется метод Contains() с указанным ключом искомого элемента. С помощью мето да GetEnumerator() получается перечислитель, совместимый с коллекцией типа IDictionary. Этот перечислитель оперирует парами "ключ-значение". В интерфейсе IDictionary определяются перечисленные ниже свойства. Следует иметь в виду, что ключи и значения, содержащиеся в коллекции, доступны в отдельных списках с помощью свойств Keys и Values. Кроме того, в интерфейсе IDictionary определяется следующий индексатор. object this[object key] { get; set; } Метод Описание void Add(object key, object value) void Clear() Добавляет в вызывающую коллекцию пару "ключ- значение”, определяемую параметрами key и value Удаляет все пары "ключ-значение" из вызывающей коллекции bool Contains(object key) Возвращает логическое значение true, если вызываю щая коллекция содержит объект key в качестве ключа, в противном случае — логическое значение false IDictionaryEnumerator GetEnumerator() Возвращает перечислитель для вызывающей коллек ции void Remove(object key) Удаляет из коллекции элемент, ключ которого равен зна чению параметра key Свойство Назначение bool IsFixedSize { get; } Принимает логическое значение true, если словарь имеет фиксированный размер bool IsReadOnly { get; } Принимает логическое значение true, если словарь до ступен только для чтения ICollection Keys { get; } Получает коллекцию ключей ICollection Values { get; } Получает коллекцию значений Этот индексатор служит для получения и установки значения элемента коллекции, а также для добавления в коллекцию нового элемента. Но в качестве индекса в данном случае служит ключ элемента, а не собственно индекс. Интерфейсы IEnumerable, IEnumerator и IDictionaryEnumerator Интерфейс IEnumerable является необобщенным, и поэтому он должен быть реализован в классе для поддержки перечислителей. Как пояснялось выше, интер фейс IEnumerable реализуется во всех классах необобщенных коллекций, посколь ку он наследуется интерфейсом ICollection. Ниже приведен единственный метод GetEnumerator(), определяемый в интерфейсе IEnumerable. IEnumerator GetEnumerator() Он возвращает коллекцию. Благодаря реализации интерфейса IEnumerable мож но также получать содержимое коллекции в цикле foreach. В интерфейсе IEnumerator определяются функции перечислителя. С помощью ме тодов этого интерфейса можно циклически обращаться к содержимому коллекции. Если в коллекции содержатся пары "ключ-значение" (словари), то метод GetEnumerator() возвращает объект типа IDictionaryEnumerator, а не типа IEnumerator. Интерфейс IDictionaryEnumerator наследует от интерфейса IEnumerator и вводит дополни тельные функции, упрощающие перечисление словарей. В интерфейсе IEnumerator определяются также методы MoveNext() и Reset() и свойство Current. Способы их применения подробнее описываются далее в этой главе. А до тех пор следует отметить, что свойство Current содержит элемент, полу чаемый в текущий момент. Метод MoveNext() осуществляет переход к следующему элементу коллекции, а метод Reset() возобновляет перечисление с самого начала. Интерфейсы IComparer и IEqualityComparer В интерфейсе IComparer определяется метод Compare() для сравнения двух объектов. int Compare(object х, object у) Он возвращает положительное значение, если значение объекта х больше, чем у объекта у; отрицательное — если значение объекта х меньше, чем у объекта у; и ну левое — если сравниваемые значения равны. Данный интерфейс можно использовать для указания способа сортировки элементов коллекции. В интерфейсе IEqualityComparer определяются два метода. bool Equals(object х, object у) int GetHashCode(object obj) Метод Equals() возвращает логическое значение true, если значения объектов х и у равны. А метод GetHashCode() возвращает хеш-код для объекта obj. Интерфейсы IStructuralComparable и IStructuralEquatable Оба интерфейса IStructuralComparable и IStructuralEquatable добавлены в версию 4.0 среды .NET Framework. В интерфейсе IStructuralComparable определя ется метод CompareTo(), который задает способ структурного сравнения двух объектов для целей сортировки. (Иными словами, Метод CompareTo() сравнивает содержимое объектов, а не ссылки на них.) Ниже приведена форма объявления данного метода. int CompareTo(object other, IComparer comparer) Он должен возвращать -1, если вызывающий объект предшествует другому объекту other; 1, если вызывающий объект следует после объекта other; и наконец, 0, если значения обоих объектов одинаковы для целей сортировки. А само сравнение обеспе чивает объект, передаваемый через параметр comparer. Интерфейс IStructuralEquatable служит для выяснения структурного равен ства путем сравнения содержимого двух объектов. В этом интерфейсе определены сле дующие методы. bool Equals(object other, IEqualityComparer comparer) int GetHashCode(IEqualityComparer comparer) Метод Equals() должен возвращать логическое значение true, если вызывающий объект и другой объект other равны. А метод GetHashCode() должен возвращать хеш-код для вызывающего объекта. Результаты, возвращаемые обоими методами, должны быть совместимы. Само сравнение обеспечивает объект, передаваемый через параметр comparer. Структура DictionaryEntry В пространстве имен System.Collections определена структура DictionaryEntry. Необобщенные коллекции пар "ключ-значение" сохраняют эти пары в объекте типа DictionaryEntry. В данной структуре определяются два следующих свойства. public object Key { get; set; } public object Value { get; set; } Эти свойства служат для доступа к ключу или значению, связанному с элементом коллекции. Объект типа DictionaryEntry может быть сконструирован с помощью конструктора: public DictionaryEntry(object key, object value) где key обозначает ключ, a value — значение. Классы необобщенных коллекций А теперь, когда представлены интерфейсы необобщенных коллекций, можно пе рейти к рассмотрению стандартных классов, в которых они реализуются. Ниже при ведены классы необобщенных коллекций, за исключением коллекции типа BitArray, рассматриваемой далее в этой главе. Класс Описание ArrayList Определяет динамический массив, т.е. такой массив, который может при необходимости увеличивать свой размер Hashtable Определяет хеш-таблицу для пар “ключ-значение” Queue Определяет очередь, или список, действующий по принципу “первым при шел — первым обслужен” SortedList Определяет отсортированный список пар “ключ-значение” Stack Определяет стек, или список, действующий по принципу "первым пришел — последним обслужен” Каждый из этих классов коллекций подробно рассматривается и демонстрируется далее на конкретных примерах. Класс ArrayList В классе ArrayList поддерживаются динамические массивы, расширяющиеся и сокращающиеся по мере необходимости. В языке C# стандартные массивы имеют фик сированную длину, которая не может изменяться во время выполнения программы. Это означает, что количество элементов в массиве нужно знать заранее. Но иногда тре буемая конкретная длина массива остается неизвестной до самого момента выполне ния программы. Именно для таких ситуаций и предназначен класс ArrayList. В клас се ArrayList определяется массив переменной длины, который состоит из ссылок на объекты и может динамически увеличивать и уменьшать свой размер. Массив типа ArrayList создается с первоначальным размером. Если этот размер превышается, то массив автоматически расширяется. А при удалении объектов из такого массива он автоматически сокращается. Коллекции класса ArrayList широко применяются в практике программирования на С#. Именно поэтому они рассматриваются здесь под робно. Но многие способы применения коллекций класса ArrayList распространя ются и на другие коллекции, в том числе и на обобщенные. В классе ArrayList реализуются интерфейсы ICollection, IList, IEnumerable и ICloneable. Ниже приведены конструкторы класса ArrayList. public ArrayList() public ArrayList(ICollection c) public ArrayList(int capacity) Первый конструктор создает пустую коллекцию класса ArrayList с нулевой перво начальной емкостью. Второй конструктор создает коллекцию типа ArrayList с коли чеством инициализируемых элементов, которое определяется параметром с и равно первоначальной емкости массива. Третий конструктор создает коллекцию, имеющую указанную первоначальную емкость, определяемую параметром сараcity. В данном случае емкость обозначает размер базового массива, используемого для хранения эле ментов коллекции. Емкость коллекции типа ArrayList может увеличиваться автома тически по мере добавления в нее элементов. В классе ArrayList определяется ряд собственных методов, помимо тех, что уже объявлены в интерфейсах, которые в нем реализуются. Некоторые из наиболее часто используемых методов класса ArrayList перечислены в табл. 25.4. Коллекцию класса ArrayList можно отсортировать, вызвав метод Sort(). В этом случае поиск в отсо ртированной коллекции с помощью метода BinarySearch() становится еще более эффективным. Содержимое коллекции типа ArrayList можно также обратить, вы звав метод Reverse(). Таблица 25.4. Наиболее часто используемые методы, определенные в классе ArrayList Метод Описание public virtual void AddRange(Icollection с) public virtual int BinarySearch(object value) Добавляет элементы из коллекции с в конец вызываю щей коллекции типа ArrayList Выполняет поиск в вызывающей коллекции значения value. Возвращает индекс найденного элемента. Если искомое значение не найдено, возвращает отрицатель ное значение. Вызывающий список должен быть отсо ртирован Продолжение табл. 25.4 Метод Описание public virtual int BinarySearch(object value, Icomparer comparer) Выполняет поиск в вызывающей коллекции значения value, используя для сравнения способ, определяемый параметром comparer. Возвращает индекс совпавше го элемента. Если искомое значение не найдено, воз вращает отрицательное значение. Вызывающий список должен быть отсортирован public virtual int BinarySearch(int index, int count, object value, IComparer comparer) Выполняет поиск в вызывающей коллекции значения value, используя для сравнения способ, определяемый параметром comparer. Поиск начинается с элемента, указываемого по индексу index, и включает количество элементов, определяемых параметром count. Метод воз вращает индекс совпавшего элемента. Если искомое зна чение не найдено, метод возвращает отрицательное зна чение. Вызывающий список должен быть отсортирован public virtual void СоруТо(Array array) Копирует содержимое вызывающей коллекции в мас сив array, который должен быть одномерным и совме стимым по типу с элементами коллекции public virtual void СоруТо(Array array, int arrayIndex) Копирует содержимое вызывающей коллекции в массив array, начиная с элемента, указываемого по индексу arrayIndex. Целевой массив должен быть одномер ным и совместимым по типу с элементами коллекции public virtual void CopyTo(int index, Array array, int arrayIndex, int count) Копирует часть вызывающей коллекции, начиная с эле мента, указываемого по индексу index, и включая ко личество элементов, определяемых параметром count, в массив array, начиная с элемента, указываемого по индексу arrayIndex. Целевой массив должен быть одно мерным и совместимым по типу с элементами коллекции public static ArrayList FixedSize(ArrayList list) public virtual ArrayList GetRange(int index, int count) Заключает коллекцию list в оболочку типа ArrayList с фиксированным размером и возвращает результат Возвращает часть вызывающей коллекции типа ArrayList. Часть возвращаемой коллекции начинает ся с элемента, указываемого по индексу index, и вклю чает количество элементов, определяемое параметром count. Возвращаемый объект ссылается на те же эле менты, что и вызывающий объект public virtual int IndexOf(object value) Возвращает индекс первого вхождения объекта value в вызывающей коллекции. Если искомый объект не об наружен, возвращает значение -1 public virtual void InsertRange(int index, ICollection c) Вставляет элементы коллекции с в вызывающую кол лекцию, начиная с элемента, указываемого по индексу index public virtual int LastlndexOf(object value) Возвращает индекс последнего вхождения объекта value в вызывающей коллекции. Если искомый объект не обнаружен, метод возвращает значение -1 Окончание табл. 25.4 В классе ArrayList поддерживается также ряд методов, оперирующих элемента ми коллекции в заданных пределах. Так, в одну коллекцию типа ArrayList можно вставить другую коллекцию, вызвав метод InsertRange(). Для удаления из коллек ции элементов в заданных пределах достаточно вызвать метод RemoveRange(). А для Метод Описание public static ArrayList Readonly(ArrayList list) Заключает коллекцию list в оболочку типа ArrayList, доступную только для чтения, и возвра щает результат public virtual void RemoveRange(int index, int count) Удаляет часть вызывающей коллекции, начиная с эле мента, указываемого по индексу index, и включая количество элементов, определяемое параметром count public virtual void Reverse() Располагает элементы вызывающей коллекции в обрат ном порядке public virtual void Reverse(int index, int count) Располагает в обратном порядке часть вызывающей коллекции, начиная с элемента, указываемого по индек су index, и включая количество элементов, определяе мое параметром count public virtual void SetRange(int index, ICollection c) Заменяет часть вызывающей коллекции, начиная с эле мента, указываемого по индексу index, элементами коллекции с public virtual void Sort() Сортирует вызывающую коллекцию по нарастающей public virtual void Sort(Icomparer comparer) Сортирует вызывающую коллекцию, используя для срав нения способ, определяемый параметром comparer. Если параметр comparer имеет пустое значение, то для сравнения используется способ, выбираемый по умолчанию public virtual void Sort(int index, int count, Icomparer comparer) Сортирует вызывающую коллекцию, используя для срав нения способ, определяемый параметром comparer. Сортировка начинается с элемента, указываемого по индексу index, и включает количество элементов, определяемых параметром count. Если параметр comparer имеет пустое значение, то для сравнения ис пользуется способ, выбираемый по умолчанию public static ArrayList Synchronized