Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
4 сем Инфа готово.docx
Скачиваний:
24
Добавлен:
04.06.2015
Размер:
255.66 Кб
Скачать

Вопрос 32. Коллекции в .Net

Пространство имен System.Collections содержит интерфейсы и классы, определяющие различные коллекции объектов, такие как списки, очереди, хеш-таблицы и словари, которые можно использовать как непосредственно, так и для реализации собственных коллекций. Для обработки всех элементов коллекций, так же как и для массивов, может быть применен цикл foreach.

Обобщения позволяют определять типобезопасные структуры данных, не указывая конкретных типов данных. Это позволяет существенно увеличить производительность и качество кода, так как позволяет повторно использовать алгоритмы обработки данных не размножая специфичный для типов код. По сути обобщения похожи на шаблоны С++, но существенно отличаются от них по реализации и возможностям.

Все мы сталкивались с задачами, которые встречаются в программировании настолько часто, что их просто лень каждый раз реализововать. Списки, стэки, очереди и многие другие приёмы используются настолько часто, что их можно было бы написать один раз, и забыть. С этой идеей мы уже знакомы - Standart Template Library в C++. В C# эту роль играет System.Collections. Среда .NET Framework поддерживает три основных типа коллекций: общего назначения, специализированные и ориентированные на побитовую организацию данных.

Коллекции общего назначения реализуют ряд основных структур данных, включая динамический массив, стек и очередь. Сюда также относятся словари, предназначенные для хранения пар ключ/значение. Коллекции общего назначения работают с данными типа object (как вы помните, любой класс наследуется от этого класса), поэтому их можно использовать для хранения данных любого типа.

Коллекции специального назначения ориентированы на обработку данных конкретного типа или на обработку уникальным способом. Например, существуют специализированные коллекции, предназначенные только для обработки строк или однонаправленного списка.

Классы коллекций, ориентированных на побитовую организацию данных, служат для хранения групп битов. Коллекции этой категории поддерживают такой набор операций, который не характерен для коллекций других типов. Например, в известной многим бит-ориентированной коллекции Bit Array определены такие побитовые операции, как И и исключающее ИЛИ.

Основополагающим для всех коллекций является реализация перечислителя (нумератора), который поддерживается интерфейсами IEnumerator и IEnumerable. Перечислитель обеспечивает стандартизованный способ поэлементного доступа к содержимому коллекции. Любая коллекция должна реализовывать интерфейс IEnumerable, и делается это специально для того, чтобы элементам любого класса коллекции можно было бы получить доступ с помощью методов, определенных в интерфейсе IEnumerator. Содержимое коллекции любого типа можно

опросить с помощью нумератора, используемого в цикле foreach. То, что в C++ называется контейнером, в С# именуется коллекцией.

В пространстве имён System.Collections определены следующие интерфейсы:

ICollection - Определяет элементы, которые должны иметь все коллекции

IEnumerable - Определяет метод GetEnumerator ( ) , который поддерживает нумератор для любого класса коллекции

IEnumerator - Содержит методы, которые позволяют поэлементно получать содержимое коллекции

IList - Определяет коллекцию, к которой можно получить доступ посредством индексатора

IDictionary - Определяет коллекцию, которая состоит из пар ключ/значение

IDictionaryEnumerator - Определяет нумератор для коллекции, которая реализует интерфейс

IComparer - Определяет метод Compare ( ) , который выполняет сравнение объектов, хранимых в коллекции

IHashCodeProvider - Определяет хеш-функцию. Внимание! Далее идёт теоретическая часть, рассказывающая про устройство всех этих интерфейсов, рано или поздно к ней придётся вернуться, но для начала её можно пропустить, а сперва ознакомиться с уже реализованными коллециями. ---------------------------------------------------------------------------------------------------------------------------------------------------------

Интерфейс ICollection можно назвать фундаментом, на котором построены все коллекции. В нем объявлены основные методы и свойства, без которых не может обойтись ни одна коллекция. Он наследует интерфейс IEnumerable.В интерфейсе ICollection определены следующие свойства:

int count { get; } : Количество элементов коллекции в данный момент

bool isSynchromzed { get; } : Принимает значение true , если коллекция синхронизирована, и значение false в противном случае По умолчанию коллекции не синхронизированы Но для большинства коллекций можно получить синхронизированную версию

object syncRoot { get; } : Объект, для которого коллекция может быть синхронизирована.

Свойство Count —самое востребованное, поскольку содержит количество элементов, хранимых в коллекции в данный момент. Если свойство Count равно нулю, значит, коллекция пуста. В интерфейсе ICollection определен следующий метод:

void CopyTo (Array target, int startldx)

Метод CopyTo () копирует содержимое коллекции в массив, заданный параметром target, начиная с индекса, заданного параметром startldx. Можно сказать, что метод CopyTo() обеспечивает переход от коллекции к стандартному С#-массиву. Поскольку интерфейс ICollection наследует интерфейс IEnumerable, он также включает его единственный метод GetEnumerator(), который возвращает нумератор коллекции (IEnumerator).

Интерфейс IList наследует интерфейс ICollection и определяет поведение коллекции, доступ к элементам которой разрешен посредством индекса с отсчетом от нуля. Помимо методов, определенных в интерфейсе ICollection, интерфейс IList определяет и собственные методы:

int Add(object obj) - Добавляет объект obj в вызывающую коллекцию. Возвращает индекс, по которому этот объект сохранен

void Clear() - Удаляет все элементы из вызывающей коллекции.

bool Contains(object obj) - Возвращает значение true , если вызывающая коллекция содержит объект, переданный в параметре obj, и значение false в противном случае.

int IndexOf(object obj) - Возвращает индекс объекта obj, если он (объект) содержится в вызывающей коллекции. Если объект obj не обнаружен, метод возвращает -1.

void Insert(int idx, object obj) - Вставляет в вызывающую коллекцию объект obj по индексу, заданному параметром idx. Элементы, находившиеся до этого по индексу idx и далее, смещаются вперед, чтобы освободить место для вставляемого объекта obj.

void Remove(object obj) - Удаляет первое вхождение объекта obj из вызывающей коллекции. Элементы, находившиеся до этого за удаленным элементом, смещаются назад, чтобы ликвидировать образовавшуюся "брешь".

void RemoveAt(int idx) - Удаляет из вызывающей коллекции объект, расположенный по индексу, заданному параметром idx. Элементы, находившиеся до этого за удаленным элементом, смещаются назад, чтобы ликвидировать образовавшуюся "брешь".

Объекты добавляются в коллекцию типа IList посредством вызова метода Add(). Как видно выше, метод Add() принимает аргументы типа object. Поскольку класс object является базовым для всех типов, в коллекции можно сохранить объект любого типа. Это справедливо и для типов значений (нессылочных типов), поскольку здесь автоматически выполняется приведение к объектному типу (boxing). Удалить объект из коллекции можно с помощью метода Remove() или RemoveAt(). Метод Remove() удаляет заданный объект, а метод RemoveAt () — объект, расположенный по заданному индексу. Для полной очистки коллекции достаточно вызвать метод Clear().

Чтобы узнать, содержит ли коллекция заданный объект, вызовите метод Contains(). Получить индекс заданного объекта поможет метод IndexOf ( ), а вставить элемент по заданному индексу — метод Insert().В классе iList определены следующие свойства:

bool IsFixedSize { get; }

bool IsReadOnly { get; }

Если коллекция имеет фиксированный размер, свойство IsFixedSize принимает значение true. Это означает, что в такую коллекцию нельзя вставлять элементы и удалять их из нее. Если коллекция предназначена только для чтения, свойство IsReadOnly имеет значение true. Это говорит о том, что содержимое коллекции изменению не подлежит. В классе IList определен следующий индексатор:

object this[int idx] { get; set; }

Этот индексатор можно использовать для считывания или записи значения нужного элемента. Но его нельзя применить для добавления в коллекцию нового элемента. Для этой цели существует метод Add (). Но после того как элемент добавлен в коллекцию, к нему можно получить доступ с помощью индексатора.

Интерфейс IDictionary определяет поведение коллекции, которая устанавливает соответствие между уникальными ключами и значениями. Ключ -— это объект, который используется для получения соответствующего ему значения. Следовательно, коллекция, которая реализует интерфейс IDictionary, служит для хранения пар ключ/значение. Сохраненную однажды пару можно затем извлечь по заданному ключу. Интерфейс IDictionary наследует интерфейс iCollection.

void Add(object к, object v) - Добавляет в вызывающую коллекцию пару ключ/значение, заданную параметрами к и v. Ключ к не должен быть нулевым. Если окажется, что ключ к

уже хранится в коллекции, генерируется исключение типа ArgumentException.

void Clear() - Удаляет все пары ключ/значение из вызывающей коллекции.

bool contains(object к) - Возвращает значение true, если вызывающая коллекция содержит объект в качестве ключа. В противном случае возвращает значение false.

iDictionaryEnumerator GetEnumerator() - Возвращает нумератор для вызывающей коллекции.

void Remove (object к) - Удаляет элемент, ключ которого равен значению к.

Чтобы добавить пару ключ/значение в lDictionary-коллекцию, используйте метод Add (). Обратите внимание на то, что ключ и его значение задаются как отдельные параметры. Чтобы удалить из коллекции-словаря ненужный элемент, необходимо передать методу Remove () соответствующий ему ключ. Для очистки всей коллекции используется метод Clear().Чтобы определить, содержит ли коллекция заданный объект, достаточно вызвать метод Contains(), передав ему ключ интересующего вас объекта. Метод GetEnumerator () возвращает нумератор, совместимый с коллекцией IDictionary. Этот нумератор работает в "парном" (ключ/значение) режиме.

В интерфейсе IDictionary определены следующие свойства:

bool isFixedSize { get ; } - Равно значению true , если словарь имеет фиксированный размер.

bool isReadOnly { get ; } - Равно значению true , если словарь предназначен только для чтения.

ICollection Keys { get ; } - Получает коллекцию ключей

ICollection Values { get; } - Получает коллекцию значений

Обратите внимание на то, что с помощью свойств Keys и Values ключи и значения, хранимые в словарной коллекции, можно получить в видеотдельных списков. В интерфейсе IDictionary определен следующий индексатор:

object this[object key] { get; set; }

Этот индексатор можно использовать для получения или установки значения элемента. Его можно также использовать для добавления в коллекцию нового элемента. Обратите внимание на то, что "индекс" в данном случае не является обычным индексом, а ключом элемента.

Интерфейс IEnumerable должен быть реализован в любом классе, если в нем предполагается поддержка нумераторов. Как упоминалось выше, все классы коллекций реализуют интерфейс IEnumerable, поскольку он наследуется интерфейсом ICollection. В интерфейсе IEnumerable определен единственный метод IEnumerator GetEnumerator(). Он возвращает нумератор для коллекции. Кроме того, реализация интерфейса IEnumerable позволяет получить доступ к содержимому коллекции с помощью цикла foreach. Интерфейс IEnumerator, собственно, и определяет действие любого нумератора. Используя его методы, можно циклически опросить содержимое коллекции. Для коллекций, в которых хранятся пары ключ/ значение (т.е. словари), метод GetEnumerator () возвращает объект типа IDictionaryEnumerator, а не типа IEnumerator. Класс IDictionaryEnumerator является производным от класса IEnumerator и распространяет свои функциональные возможности нумератора на область словарей.

В интерфейсе IComparer определен метод Compare (), который позволяет сравнивать два объекта:

int Compare(object v1, object v2)Метод Compare () возвращает положительное число, если значение v1 больше значения v2, отрицательное, если v1 меньше v2, и нуль, если сравниваемые значения равны. Этот интерфейс можно использовать для задания способа сортировки элементов коллекции.

Интерфейс IHashCodeProvider должен быть реализован коллекцией, если программисту необходимо определить собственную версию метода GetHashCode(). Вспомните, что все объекты (для получения хеш-кода) наследуют метод Object GetHashCode (), который используется по умолчанию. Посредством реализации интерфейса IHashCodeProvider можно определить альтернативный метод.

В пространстве имен System.Collections опреден тип структуры с именем DictionaryEntry. Коллекции, в которых хранятся пары ключ/значение, используют для их хранения объект типа DictionaryEntry. В этой структуре определены следующие два свойства:

public object Key { get; set; }

public object Value { get; set; }

Эти свойства используются для получения доступа к ключу или к соответствующему ему значению. Объект типа DictionaryEntry можно создать с помощью следующего конструктора:

public DictionaryEntry(object k, object v)

Здесь параметр k принимает ключ, а параметр v — значение.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]