This documentation is archived and is not being maintained.

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<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. For these reasons, we strongly recommend that you use generic collection classes whenever possible.

All collections that directly or indirectly implement the ICollection interface or the ICollection<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 (System.Collections classes only).

    On legacy collection types in the System.Collections namespace, synchronization provides some degree of thread safety when accessing elements of the collection. The collections are not thread safe by default. If you require scalable and efficient multi-threaded access to a collection, use one of the classes in the System.Collections.Concurrent namespace. For more information, see Thread-Safe Collections.

    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<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<T> generic interface has additional members, which the nongeneric interface does not include.

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 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. Many commonly used collections have nongeneric versions, generic versions, and thread-safe generic 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. For tips on choosing a collection, see Selecting a Collection Class.