Updated on September 21th 2020 with IReadOnlySet<T>
Sometimes, the proper choice of a collection can greatly impact the performance of your application. For example, there are collection types that are more appropriate for insertions, others that allow faster lookups, and so on. Plus, you must decide if you want indexed collections or not, and if you want to have generic collections, in order to have compile-time type checking. The .NET BCL comes with several general-purpose collection classes. Here is a list of all the collection classes in .NET 4.5 (plus the Immutable Collections library) and their intended use.
Purpose | Types | Description |
Fixed size |
System.Array, System.Collections.Immutable.ImmutableArray<T> |
Can have multiple dimensions |
FIFOs (Queues) |
System.Collections.Queue, System.Collections.Generic.Queue<T>, System.Collections.Concurrent.ConcurrentQueue<T>, System.Collections.Immutable.ImmutableQueue<T> |
First in, first out |
LIFOs (Stacks) |
System.Collections.Stack, System.Collections.Generic.Stack<T>, System.Collections.Concurrent.ConcurrentStack<T>, System.Collections.Immutable.ImmutableStack<T> |
Last in, first out |
Linked lists |
System.Collections.Generic.LinkedList<T> |
Random inserts and deletes |
Array-based |
System.Collections.ArrayList, System.Collections.Generic.List<T>, System.Collections.Concurrent.ConcurrentBag<T>, System.Collections.Immutable.ImmutableList<T> |
|
Customizable |
System.Collections.ObjectModel.Collection<T> |
Can override InsertItem, RemoveItem, SetItem and ClearItems to implement custom algorithms |
Thread-safe |
System.Collections.Generic.SynchronizedCollection<T>, System.Collections.Generic.SynchronizedReadOnlyCollection<T> |
Thread-safe |
Read-only |
System.Collections.ObjectModel.ReadOnlyCollection<T>, System.Collections.Generic.SynchronizedReadOnlyCollection<T>, System.Collections.ObjectModel.ReadOnlyObservableCollection<T> |
Wrap existing (not read-only collections) |
Sorted |
System.Collections.SortedList, System.Collections.Generic.SortedList<K, V>, System.Collections.Generic.SortedDictionary<K, V>, System.Collections.Generic.SortedSet<T>
|
Sorted by key |
Sets |
System.Collections.Generic.HashSet<T>, System.Collections.SortedSet<T>, System.Collections.Immutable.ImmutableSortedSet<T>, System.Collections.Immutable.ImmutableHashSet<T>, |
No repetition of elements |
Keyed |
System.Collections.Specialized.ListDictionary (for <=10 items), System.Collections.Generic.Dictionary<K, V>, System.Collections.Hashtable (index by hash), System.Collections.Generic.KeyedByTypeCollection<T> (index by type), System.Collections.Specialized.HybridDictionary (changes depending on number of elements, ListDictionary -> Hashtable), System.Collections.Specialized.OrderedDictionary (access by key or index), System.Collections.Immutable.ImmutableDictionary<K, V>, System.Collections.Concurrent.ConcurrentDictionary<K, V>, System.Collections.Immutable.ImmutableSortedDictionary<K, V> |
Single value per key |
Multiple values for a single key |
System.Collections.Specialized.NameValueCollection |
|
Bits |
System.Collections.BitArray, System.Collections.BitVector32 (up to 32 bits only) |
Bit operations |
Strings |
System.Collections.Specialized.StringDictionary, System.Collections.Specialized.StringCollection |
Strings |
Observable |
System.Collections.ObjectModel.ObservableCollection<T>, System.Collections.ObjectModel. ReadOnlyObservableCollection<T> |
Identical to System.Collections.ObjectModel.Collection<T>, fires events upon adding, removing, modifying or clearing. |
Concurrent |
System.Collections.Concurrent.BlockingCollection<T>, System.Collections.Concurrent.ConcurrentBag<T>, System.Collections.Concurrent.ConcurrentDictionary<K, V>, System.Collections.Concurrent.ConcurrentQueue<T>, System.Collections.Concurrent.ConcurrentStack<T> |
Thread-safe, lock-free |
Immutable |
System.Collections.Immutable.ImmutableDictionary<K, V>, System.Collections.Immutable.ImmutableHashSet<T>, System.Collections.Immutable.ImmutableList<T>, System.Collections.Immutable.ImmutableQueue<T>, System.Collections.Immutable.ImmutableSortedDictionary<K, V>, System.Collections.Immutable.ImmutableSortedSet<T>, System.Collections.Immutable.ImmutableStack<T>, System.Collections.Immutable.ImmutableArray<T> |
Immutable collections (see http://msdn.microsoft.com/en-us/library/dn385366.aspx) |
Of course, you should not expose a collection class directly, instead you should use collection interfaces, that all these classes implement (at least, one of them). These interfaces are:
Purpose | Types |
Enumerate, count |
System.Collections.ICollection, System.Collections.Generic.ICollection<T> |
Indexed access, add/remove |
System.Collections.IList, System.Collections.Generic.IList<T>, System.Collections.Immutable.IImmutableList<T>, System.Collections.Generic.IReadOnlyList<Y>, System.Collections.Generic.IReadOnlyCollection<T> |
Keyed |
System.Collections.IDictionary, System.Collections.Specialized.IOrderedDictionary, System.Collections.Generic.IDictionary<K, V>, System.Collections.Generic.IReadOnlyDictionary<K, V>, System.Collections.Immutable.IImmutableDictionary<K, V> |
Enumerate only |
System.Collections.IEnumerable, System.Collections.IEnumerable<T>, System.Linq.IOrderedEnumerable<T>, System.Linq.ILookup<K, E> (multiple values per key) |
Queues |
System.Collections.Immutable.IImmutableQueue<T> |
Stacks |
System.Collections.Immutable.IImmutableStack<T> |
Sets |
System.Collections.Generic.ISet<T>, System.Collections.Immutable.IImmutableSet<T>, System.Collections.Generic.IReadOnlySet<T> |
Some recommendations for using collections:
And that's it.