Generic and Non-Generic Collection Interfaces in C#

Dated Sep 6, 2025; last modified on Sat, 06 Sep 2025

There are two main types of collections: non-generic (ICollection) and generic (ICollection<T>).

Non-generic collections only exist because .NET did not originally have generic data types. They shouldn’t be used because:

  • They are untyped at compile time. The frequent casting from object and the actual type is error-prone; it’s easy to put the wrong type in the wrong collection.
  • Value types need to be boxed as object, e.g., List<int> stores its data in an int[], which is more performant than using object[] as that requires boxing.

Non-Generic Collections (ICollection)

ICollection extends IEnumerable.

Properties of ICollection

Count gets the number of elements contained in the ICollection.

This is different from the capacity, which is the number of elements that a collection can contain. For most collections, when the current capacity is reached, the memory is reallocated, and the elements are copied from the old collection to the new one. To avoid poor performance from multiple reallocations, set the initial capacity to the estimated size of the collection.

IsSynchronized is true if access to the ICollection is thread-safe.

SyncRoot is an object that can be used to synchronize the ICollection.

Methods of ICollection

CopyTo copies the elements of the collection to an Array starting at a particular Array index.

GetEnumerator is an enumerator that iterates through a collection.

Extension Methods of ICollection

Cast<TResult> casts the elements of an IEnumerable to TResult.

I still don’t understand the rationale. In , Cast helped me iterate over a multi-dimensional array. Why wouldn’t the multi-dimensional array expose LINQ methods instead of needing Cast?

OfType<TResult> filters the TResult instances in an IEnumerable.

AsParallel enables parallelization of a query.

AsQueryable converts an IEnumerable into an IQueryable.

Generic Collections (ICollection<T>)

ICollection<T> extends IEnumerable<T>.

Properties of ICollection<T>

Compared to ICollection, keeps Count, but lacks IsSynchronized and SyncRoot.

IsReadOnlye is true if the ICollection<T> is read-only.

Methods of ICollection<T>

Compared to ICollection, keeps CopyTo and GetEnumerator.

Add, Clear, Contains, and Remove.

Extension Methods of ICollection<T>

Compared to ICollection, keeps Cast, OfType, AsParallel, and AsQueryable.

Conversion to Other Collection Types

ToFrozen* for Dictionary and Set create immutable, read-only collections that are optimized for fast lookup and enumeration.

To* and ToImmutable* for Array, Dictionary, HashSet, List, SortedDictionary, and SortedSet. Additionally, ToLookup creates a collection of keys mapped to one or more values .

Filtering Elements in a Sequence

All and Any test elements in the sequence against a predicate.

Where filters a sequence of values based on a predicate.

Distinct and DistinctBy produce distinct elements from a sequence.

Fetching and Adding Scalars

Single returns the only element that satisfies the predicate and throws if more than one such element exists. SingleOrDefault is like Single but returns a default value if no such element exists.

Prepend and Append add a value to the beginning and end of a sequence, respectively.

First, FirstOrDefault, Last, LastOrDefault, ElementAt and ElementAtOrDefault for index-based selection.

Operating on Multiple Sequences

Concat concatenates two sequences.

Set operations between two sequences: Except and ExceptBy for the difference; Intersect and IntersectBy for the intersection; Union and UnionBy for the union.

Join and GroupJoin correlates elements of two sequences by a specified key.

SequenceEqual tests whether two sequences are equal.

Projecting Elements to a Different Type

Select projects each element into a new form. SelectMany flattens the resulting sequences into one sequence.

AsEnumerable changes the compile-time type of source from a type that implements IEnumerable<T> to IEnumerable<T> itself. Sample use-case: foregoing a custom implementation of Where().

Reducing a Sequence

Aggregate and AggregateBy apply an accumulator function, akin to reduce in other languages. There are mathematical aggregations such as Average, Max, MaxBy, Min, MinBy, and Sum.

Count and CountBy count the number of elements that satisfy a predicate. LongCount is similar but returns an Int64. TryGetNonEnumeratedCount attempts to get the count without forcing an enumeration.

Iterating Through a Sequence

Chunk splits the elements of a sequence into chunks of size at most size.

DefaultIfEmpty returns the sequence if non-empty and otherwise returns a singleton collection with the defined default value.

GroupBy groups the elements of a sequence by a specified key.

Index returns an enumerable that incorporates the element’s index into a tuple.

Order, OrderDescending, OrderBy, and OrderByDescending sort the elements of a sequence.

Reverse inverts the order of elements in a sequence.

Skip and SkipLast bypass a specified number of elements in the sequence and returns the remaining ones. SkipWhile checks a predicate instead of counting. Take, TakeLast, and TakeWhile are inverses.

Zip produces a sequence of tuples with elements from two/three sequences, or two sequences and a computed sequence.

References

  1. Collections and Data Structures - .NET | Microsoft Learn. learn.microsoft.com . Accessed Sep 6, 2025.
  2. platform-compat/docs/DE0006.md at master ยท dotnet/platform-compat. github.com . Accessed Sep 6, 2025.
  3. ICollection Interface (System.Collections) | Microsoft Learn. learn.microsoft.com . Accessed Sep 6, 2025.
  4. ICollection<T> Interface (System.Collections.Generic) | Microsoft Learn. learn.microsoft.com . Accessed Sep 6, 2025.
  5. System.Collections.Frozen Namespace | Microsoft Learn. learn.microsoft.com . Accessed Sep 6, 2025.
  6. Lookup<TKey,TElement> Class (System.Linq) | Microsoft Learn. learn.microsoft.com . Accessed Sep 6, 2025.
  7. Enumerable.AsEnumerable<TSource>(IEnumerable<TSource>) Method (System.Linq) | Microsoft Learn. learn.microsoft.com . Accessed Sep 6, 2025.