Collections and Data Structures



Closely related data can be handled more efficiently when grouped together into a collection. Instead of writing separate code to handle each individual object, you can use the same code to process all the elements of a collection.

To manage a collection, use the Array class and the System.Collections classes to add, remove, and modify either individual elements of the collection or a range of elements. An entire collection can even be copied to another collection.

Some Collections classes have sorting capabilities, and most are indexed. Memory management is handled automatically, and the capacity of a collection is expanded as required. Synchronization provides thread safety when accessing members of the collection. Some Collections classes can generate wrappers that make the collection read-only or fixed-size. Any Collections class can generate its own enumerator that makes it easy to iterate through the elements.

In the .NET Framework version 2.0, generic collection classes provide new functionality and make it easy to create strongly typed collections. See the System.Collections.Generic and System.Collections.ObjectModel namespaces.

The LINQ to Objects feature allows you to use LINQ queries to access in-memory objects as long as the object type implements IEnumerable or IEnumerable<(Of <(T>)>). LINQ queries provide a common pattern for accessing data; are typically more concise and readable than standard foreach loops; and provide filtering, ordering and grouping capabilities. LINQ queries can also improve performance.

 


Коллекции и структуры данных

Связанные данные могут обрабатываться более эффективно, если они объединены в коллекцию. Вместо того чтобы писать код для обработки каждого отдельного объекта, можно использовать один и тот же код для обработки всех элементов коллекции.

Для управления коллекцией используйте класс Array и классы из пространства имен System.Collections для добавления, удаления и изменения либо отдельных элементов коллекции, либо диапазона элементов. Коллекцию можно скопировать целиком в другую коллекцию.

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

В .NET Framework, версия 2.0 классы универсальных коллекций предоставляют новые функциональные возможности и облегчают создание строго типизированных коллекций. Обратитесь к описанию пространств имен System.Collections.Generic и System.Collections.ObjectModel.

Функция LINQ to Objects позволяет использовать LINQ запросы для доступа к объектам в памяти, если объект типа реализовывает IEnumerable или IEnumerable<(Of <(T>)>). LINQ запросы предоставляют общий шаблон для доступа к данным, являются более четкими и удобочитаемыми, чем стандартные циклы foreach, а также предоставляют возможности фильтрации, сортировки и группировки. LINQ запросы также могут повысить производительность.

 


Defining Collections

A collection is a set of similarly typed objects that are grouped together.

Objects of any type can be grouped into a single collection of the type Object to take advantage of constructs that are inherent in the language. For example, the C# foreach statement (for each in Visual Basic) expects all objects in the collection to be of a single type.

However, in a collection of type Object, additional processing is done on the elements individually, such as boxing and unboxing or conversions, which affect the performance of the collection. Boxing and unboxing typically occur if storing or retrieving a value type in a collection of type Object.

Generic collections, such as List<(Of <(T>)>), and strongly typed nongeneric collections, such as StringCollection, avoid these performance hits if the type of the element is the type that the collection is intended for (for example, storing or retrieving strings from a StringCollection). In addition, strongly typed collections automatically perform type validation of each element added to the collection.

All collections that directly or indirectly implement the ICollection interface or the ICollection<(Of <(T>)>) generic interface share several features in addition to methods that add, remove, or search elements:

· An enumerator.

An enumerator is an object that iterates through its associated collection. It can be thought of as a movable pointer to any element in the collection. An enumerator can be associated with only one collection, but a collection can have multiple enumerators. The C# foreach statement (for each in Visual Basic) uses the enumerator and hides the complexity of manipulating the enumerator.

· Synchronization members.

Synchronization provides thread safety when accessing elements of the collection. The collections are not thread safe by default. Only a few classes in the System.Collections namespaces provide a Synchronize method that creates a thread-safe wrapper over the collection. However, all classes in all System.Collections namespaces provide a SyncRoot property that can be used by derived classes to create their own thread-safe wrapper. An IsSynchronized property is also provided to determine whether the collection is thread safe. Synchronization is not available in the ICollection<(Of <(T>)>) generic interface.

· The CopyTo method.

All collections can be copied to an array using the CopyTo method; however, the order of the elements in the new array is based on the sequence in which the enumerator returns them. The resulting array is always one-dimensional with a lower bound of zero.

Note that the ICollection<(Of <(T>)>) generic interface has additional members, which the nongeneric interface does not include.

 


Определение коллекций

Коллекция представляет собой набор объектов схожих типов, сгруппированных вместе.

Объекты любого типа могут быть сгруппированы в одну коллекцию типа Object, чтобы воспользоваться преимуществами конструкций, свойственных определенному языку. Например, оператор foreach языка C# (for each в Visual Basic) предполагает, что все объекты коллекции имеют один и тот же тип.

Однако в коллекции типа Object происходит дополнительная индивидуальная обработка элементов, к примеру, упаковка и распаковка или преобразования, что влияет на производительность коллекции. Упаковка и распаковка обычно происходят при сохранении или извлечении типа значений из коллекции типа Object.

Универсальные коллекции, такие как List<(Of <(T>)>) и строго типизированные неуниверсальные коллекции, такие как StringCollection, позволяют избежать проблем с производительностью, если тип элемента является типом, для которого предназначена коллекция (например, сохранение или извлечение строк из StringCollection). Кроме того, при добавлении элемента в строго типизированную коллекцию выполняется автоматическая проверка типа такого элемента.

Все коллекции, которые прямо или косвенно реализуют интерфейс ICollection или универсальный интерфейс ICollection<(Of <(T>)>) имеют несколько общих функциональных возможностей наряду с методами, которые выполняют добавление, удаление или поиск элементов:

· Перечислитель.

Перечислитель — это объект, который выполняет итерацию в связанной с ним коллекции. Можно считать, что он является перемещаемым указателем на любой элемент коллекции. Перечислитель может быть связан только с одной коллекцией, но коллекция может иметь несколько перечислителей. Оператор foreach языка C# (for each в Visual Basic) использует перечислитель и упрощает обращение с перечислителем.

· Элементы синхронизации.

Синхронизация обеспечивает потокобезопасность при доступе к элементам коллекции. По умолчанию коллекции не являются потокобезопасными. Только несколько классов в пространствах имен System.Collections предоставляют метод Synchronize, который создает потокобезопасную обертку для коллекции. Однако все классы во всех пространствах имен System.Collections предоставляют свойство SyncRoot, которое может быть использовано производными классами для создания собственной потокобезопасной обертки. Свойство IsSynchronized также используется для определения потокобезопасности коллекции. Синхронизация недоступна в универсальном интерфейсе ICollection<(Of <(T>)>).

· CopyTo метод.

Все коллекции могут быть скопированы в массив с помощью метода CopyTo; однако порядок элементов в новом массиве зависит от того, в какой последовательности их возвращает перечислитель. Результирующий массив всегда является одномерным массивом с нижней границей, равной нулю.

Обратите внимание, что универсальный интерфейс ICollection<(Of <(T>)>) имеет дополнительные члены, которые отсутствуют в ICollection.


The following features are implemented in some classes in the System.Collections namespaces:

· Capacity and count.

The capacity of a collection is the number of elements it can contain. The count of a collection is the number of elements it actually contains. A BitArray is a special case; its capacity is the same as its length, which is the same as its count. Some collections hide the capacity or the count or both.

All collections in the System.Collections namespaces automatically expand in capacity when the current capacity is reached. The memory is reallocated, and the elements are copied from the old collection to the new one. This reduces the code required to use the collection; however, the performance of the collection might still be negatively affected. The best way to avoid poor performance caused by multiple reallocations is to set the initial capacity to be the estimated size of the collection.

· Lower Bound.

The lower bound of a collection is the index of its first element. All indexed collections in the System.Collections namespaces have a lower bound of zero. Array has a lower bound of zero by default, but a different lower bound can be defined when creating an instance of the Array class using CreateInstance.

System.Collections classes can generally be categorized into three types:

· Commonly used collections.

These are the common variations of data collections, such as hash tables, queues, stacks, dictionaries, and lists. Commonly used collections have generic versions and nongeneric versions.

· Bit collections.

These are collections whose elements are bit flags. They behave slightly differently from other collections.

· Specialized collections.

These are collections with highly specific purposes, usually to handle a specific type of element, such as StringDictionary.

Be sure to choose a collection class carefully. Because each collection has its own functionality, each also has its own limitations. The more specialized a collection is, the more limited it is.

 


В некоторых классах пространств имен System.Collections реализованы следующие возможности:

· Емкость и количество элементов.

Емкость коллекции — это число элементов, которое она может содержать. Количество элементов коллекции — это число элементов, которое она реально содержит. BitArray является особым случаем; её емкость совпадает с его длиной, которая совпадает с количеством элементов коллекции. Некоторые коллекции скрывают емкость и/или количество элементов.

Все коллекции пространств имен System.Collections автоматически увеличивают емкость, если количество элементов достигает предела. Происходит перераспределение памяти, и элементы копируются из старой коллекции в новую. Это уменьшает объем кода, необходимого для использования коллекции; однако производительность при работе с такой коллекцией может ухудшиться. Наилучший способ избежать потерь производительности, вызванных множественными перераспределениями, это установить начальную вместимость, равную предполагаемому размеру коллекции.

· Нижняя граница.

Нижняя граница коллекции — это индекс ее первого элемента. Все индексированные коллекции в пространствах имен System.Collections имеют нижнюю границу, равную нулю. Array имеет нижнюю границу, равную нулю, по умолчанию, но при создании экземпляра Array с помощью CreateInstance может быть определена другая нижняя граница.

Обычно классы System.Collections можно разделить на три типа:

· Часто используемые коллекции.

Это распространенные виды коллекций данных, такие как хэш-таблицы, очереди, стеки, словари и списки. Часто используемые коллекции имеют свои универсальные и неуниверсальные версии.

· Битовые коллекции.

Это коллекции, элементами которых являются битовые флаги. Их поведение слегка отличается от поведения других коллекций.

· Специализированные коллекции.

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

Следует тщательно выбирать класс коллекции. Наряду с определенными функциональными возможностями каждая коллекция имеет также и собственные ограничения. Чем более специализированной является коллекция, тем она более ограничена.

 


Selecting a Collection Class

Be sure to choose your System.Collections class carefully. Using the wrong type can restrict your use of the collection.

Consider the following questions:

· Do you need a sequential list where the element is typically discarded after its value is retrieved?

· If yes, consider using the Queue class or the Queue<(Of <(T>)>) generic class if you need first-in-first-out (FIFO) behavior. Consider using the Stack class or the Stack<(Of <(T>)>) generic class if you need last-in-first-out (LIFO) behavior.

· If not, consider using the other collections.

· Do you need to access the elements in a certain order, such as FIFO, LIFO, or random?

· The Queue class and the Queue<(Of <(T>)>) generic class offer FIFO access.

· The Stack class and the Stack<(Of <(T>)>) generic class offer LIFO access.

· The LinkedList<(Of <(T>)>) generic class allows sequential access either from the head to the tail or from the tail to the head.

· The rest of the collections offer random access.

· Do you need to access each element by index?

· The ArrayList and StringCollection classes and the List<(Of <(T>)>) generic class offer access to their elements by the zero-based index of the element.

· The Hashtable, SortedList, ListDictionary, and StringDictionary classes, and the Dictionary<(Of <(TKey, TValue>)>) and SortedDictionary<(Of <(TKey, TValue>)>) generic classes offer access to their elements by the key of the element.

· The NameObjectCollectionBase and NameValueCollection classes, and the KeyedCollection<(Of <(TKey, TItem>)>) and SortedList<(Of <(TKey, TValue>)>) generic classes offer access to their elements by either the zero-based index or the key of the element.

 


Выбор класса коллекции

Необходимо тщательно выбирать ваш класс System.Collections. Использование неправильного типа может привести к ограничению возможностей использования коллекции.

Необходимо ответить на следующие вопросы:

· Нужен ли последовательный список, элемент которого обычно удаляется сразу после извлечения его значения?

    • Если да, то рассмотрите возможность использования класса Queue или универсального класса Queue<(Of <(T>)>), если требуется поведение по принципу "первым поступил — первым обслужен" (FIFO). Рассмотрите возможность использования класса Stack или универсального класса Stack<(Of <(T>)>), если требуется поведение по принципу "последним поступил — первым обслужен" (LIFO).
    • Если нет, то следует выбирать из остальных типов коллекций.

· Нужен ли доступ к элементам в определенном или в произвольным порядке (FIFO, LIFO)?

· Класс Queue и универсальный класс Queue<(Of <(T>)>) предоставляют доступ по принципу FIFO.

· Класс Stack и универсальный класс Stack<(Of <(T>)>) предоставляют доступ по принципу LIFO.

· Универсальный класс LinkedList<(Of <(T>)>) предоставляет последовательный доступ от начала к концу списка или наоборот.

· Остальные коллекции предоставляют произвольный доступ.

· Необходимо ли иметь доступ к каждому элементу по индексу?

· Классы ArrayList и StringCollection, и универсальный класс List<(Of <(T>)>) предоставляют доступ к своим элементам по индексу с отсчетом от нуля.

· Классы Hashtable, SortedList, ListDictionary и StringDictionary, а также универсальные классы Dictionary<(Of <(TKey, TValue>)>) и SortedDictionary<(Of <(TKey, TValue>)>) предоставляют доступ к своим элементам по ключу.

· Классы NameObjectCollectionBase и NameValueCollection, а также универсальные классы KeyedCollection<(Of <(TKey, TItem>)>) и SortedList<(Of <(TKey, TValue>)>) предоставляют доступ к своим элементам по индексу с отсчетом от нуля или по ключу.

 


· Will each element contain one value, a combination of one key and one value, or a combination of one key and multiple values?

· One value: Use any of the collections based on the IList interface or the IList<(Of <(T>)>) generic interface.

· One key and one value: Use any of the collections based on the IDictionary interface or the IDictionary<(Of <(TKey, TValue>)>) generic interface.

· One value with embedded key: Use the KeyedCollection<(Of <(TKey, TItem>)>) generic class.

· One key and multiple values: Use the NameValueCollection class.

· Do you need to sort the elements differently from how they were entered?

· The Hashtable class sorts its elements by their hash codes.

· The SortedList class and the SortedDictionary<(Of <(TKey, TValue>)>) and SortedList<(Of <(TKey, TValue>)>) generic classes sort their elements by the key, based on implementations of the IComparer interface and the IComparer<(Of <(T>)>) generic interface.

· ArrayList provides a Sort method that takes an IComparer implementation as a parameter. Its generic counterpart, the List<(Of <(T>)>) generic class, provides a Sort method that takes an implementation of the IComparer<(Of <(T>)>) generic interface as a parameter.

· Do you need fast searches and retrieval of information?

· ListDictionary is faster than Hashtable for small collections (10 items or fewer). The Dictionary<(Of <(TKey, TValue>)>) generic class provides faster lookup than the SortedDictionary<(Of <(TKey, TValue>)>) generic class.

· Do you need collections that accept only strings?

· StringCollection (based on IList) and StringDictionary (based on IDictionary) are in the System.Collections.Specialized namespace.

· In addition, you can use any of the generic collection classes in the System.Collections.Generic namespace as strongly typed string collections by specifying the String class for their generic type arguments.

 


· Будет ли каждый элемент содержать только одно значение, сочетание из одного ключа и одного значения или сочетание из одного ключа и нескольких значений?

· Одно значение. Можно использовать любую из коллекций, основанных на интерфейсе IList или на универсальном интерфейсе IList<(Of <(T>)>).

· Один ключ и одно значение. Можно использовать любую из коллекций, основанных на интерфейсе IDictionary или на универсальном интерфейсе IDictionary<(Of <(TKey, TValue>)>).

· Одно значение с внедренным ключом. Можно использовать универсальный класс KeyedCollection<(Of <(TKey, TItem>)>).

· Один ключ и несколько значений. Можно использовать класс NameValueCollection.

· Нужна ли возможность отсортировать элементы в порядке, отличном от порядка их поступления?

· Класс Hashtable сортирует свои элементы по их хэш-коду.

· Класс SortedList и универсальные классы SortedDictionary<(Of <(TKey, TValue>)>) и SortedList<(Of <(TKey, TValue>)>) сортируют свои элементы по их ключам на основе реализации интерфейса IComparer и универсального интерфейса IComparer<(Of <(T>)>).

· ArrayList предоставляет метод Sort, который принимает реализацию IComparer в качестве параметра. Его универсальный аналог — универсальный класс List<(Of <(T>)>) предоставляет метод Sort, который принимает реализацию универсального интерфейса IComparer<(Of <(T>)>) в качестве параметра.

· Необходим ли быстрый поиск и извлечение данных?

· ListDictionary быстрее, чем Hashtable для небольших коллекций (10 элементов или меньше). Универсальный класс Dictionary<(Of <(TKey, TValue>)>) предоставляет более быстрый просмотр, чем универсальный класс SortedDictionary<(Of <(TKey, TValue>)>).

· Нужна ли коллекция только для хранения строк?

· Классы StringCollection (основанный на IList) и StringDictionary (основанный на IDictionary) находятся в пространстве имен System.Collections.Specialized.

· Кроме того, можно использовать любой из универсальных классов коллекций в пространстве имен System.Collections.Generic как строго типизированную строковую коллекцию, указав класс String в качестве аргумента универсального типа.


Дата добавления: 2019-03-09; просмотров: 283; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!