C# Collections (Generic Collections and Non-Generic Collections)

M. Kannika
11 min readJan 29, 2022

C# Collections

For many applications, you want to create and manage groups of related objects. There are two ways to group objects: by creating arrays of objects, and by creating collections of objects.

Arrays are most useful for creating and working with a fixed number of strongly typed objects.

Collections provide a more flexible way to work with groups of objects. Unlike arrays, the group of objects you work with can grow and shrink dynamically as the needs of the application change. For some collections, you can assign a key to any object that you put into the collection so that you can quickly retrieve the object by using the key.

A collection is a class, so you must declare an instance of the class before you can add elements to that collection.

If your collection contains elements of only one data type, you can use one of the classes in the ‘System.Collections.Generic’ namespace. A generic collection enforces type safety so that no other data type can be added to it. When you retrieve an element from a generic collection, you do not have to determine its data type or convert it.

1. Generic collections

Generic collections are the preferred type to use as long as every element in the collection is of the same data type. Only desired data types can be added to a generic collection and this is enforced by using strong typing which reduces the possibility of errors.

The .NET framework provides a number of generic collection classes, useful for storing and manipulating data. To access a generic collection in your code, you will need to include the statement:

— — — — — — — — — — — — — — — — — — —

using System.Collections.Generic;

— — — — — — — — — — — — — — — — — — —

1.1 List<T>

A list is similar to an array, but the elements in a list can be inserted and removed dynamically.

The List<T> class requires all elements be of the same type T.

For example:

Output:

List<T> properties and methods:

  • Count

Gets the number of elements contained in the List<T>.

  • Item[Int32]

Gets or sets the element at the specified index.

  • Capacity

Gets or sets the total number of elements the internal data structure can hold without resizing.

  • Add(T)

Adds an object to the end of the List<T>.

  • Clear()

Removes all elements from the List<T>.

  • Contains(T)

Determines whether an element is in the List<T>.

  • RemoveAt(Int32)

Removes the element at the specified index of the List<T>.

  • Sort()

Sorts the elements in the entire List<T> using the default comparer.

You can check for all properties and methods of the List<T> here:

List<T> Class

— — — — — — — — — —

1.2 SortedList<TKey, TValue>

A sorted list is a collection of key/value pairs that are sorted by key.

A key can be used to access its corresponding value in the sorted list.

***Duplicate keys are ‘not’ permitted, to ensure that every key/value pair is unique.

The SortedList<TKey, TValue> class requires all key/value pairs be of the same type TKey, TValue.

For example:

Output:

SortedList<TKey, TValue> properties and methods:

  • Count
    Gets the number of key/value pairs contained in the SortedList<TKey,TValue>.
  • Item[TKey]
    Gets or sets the value associated with the specified key.
  • Keys
    Gets a collection containing the keys in the SortedList<TKey,TValue>, in sorted order.
  • Values
    Gets a collection containing the values in the SortedList<TKey,TValue>.
  • Add(TKey, TValue)
    Adds an element with the specified key and value into the SortedList<TKey,TValue>.
  • Clear()
    Removes all elements from the SortedList<TKey,TValue>.
  • ContainsKey(TKey)
    Determines whether the SortedList<TKey,TValue> contains a specific key.
  • ContainsValue(TValue)
    Determines whether the SortedList<TKey,TValue> contains a specific value.
  • Remove(TKey)
    Removes the element with the specified key from the SortedList<TKey,TValue>.
  • RemoveAt(Int32)
    Removes the element at the specified index of the SortedList<TKey,TValue>.

You can check for all properties and methods of the SortedList<TKey, TValue> here:

SortedList<TKey, TValue> Class

— — — — — — — — — —

1.3 Dictionary<TKey, TValue>

A dictionary is a collection of unique key/value pairs where a key is used to access the corresponding value.

***Duplicate keys are ‘not’ permitted, to ensure that every key/value pair is unique.

The Dictionary<TKey, TValue> class requires all key/value pairs be of the same type TKey, TValue.

For example:

Output:

Dictionary<TKey, TValue> properties and methods:

  • Count
    Gets the number of key/value pairs contained in the Dictionary<TKey,TValue>.
  • Item[TKey]
    Gets or sets the value associated with the specified key.
  • Keys
    Gets a collection containing the keys in the Dictionary<TKey,TValue>.
  • Values
    Gets a collection containing the values in the Dictionary<TKey,TValue>.
  • Add(TKey, TValue)
    Adds the specified key and value to the dictionary.
  • Clear()
    Removes all keys and values from the Dictionary<TKey,TValue>.
  • ContainsKey(TKey)
    Determines whether the Dictionary<TKey,TValue> contains the specified key.
  • ContainsValue(TValue)
    Determines whether the Dictionary<TKey,TValue> contains a specific value.
  • Remove(TKey)
    Removes the value with the specified key from the Dictionary<TKey,TValue>.
  • Remove(TKey, TValue)
    Removes the value with the specified key from the Dictionary<TKey,TValue>, and copies the element to the value parameter.

You can check for all properties and methods of the Dictionary<TKey, TValue> here:

Dictionary<TKey, TValue> Class

— — — — — — — — — —

1.4 SortedDictionary<TKey, TValue>

A sorted dictionary is a collection of key/value pairs that are sorted by key.

A key can be used to access its corresponding value in the sorted dictionary.

***Duplicate keys are ‘not’ permitted, to ensure that every key/value pair is unique.

The SortedDictionary<TKey, TValue> class requires all key/value pairs be of the same type TKey, TValue.

For example:

Output:

SortedDictionary<TKey, TValue> properties and methods:

  • Count
    Gets the number of key/value pairs contained in the SortedDictionary<TKey,TValue>.
  • Item[TKey]
    Gets or sets the value associated with the specified key.
  • Keys
    Gets a collection containing the keys in the SortedDictionary<TKey,TValue>.
  • Values
    Gets a collection containing the values in the SortedDictionary<TKey,TValue>.
  • Add(TKey, TValue)
    Adds an element with the specified key and value into the SortedDictionary<TKey,TValue>.
  • Clear()
    Removes all elements from the SortedDictionary<TKey,TValue>.
  • ContainsKey(TKey)
    Determines whether the SortedDictionary<TKey,TValue> contains an element with the specified key.
  • ContainsValue(TValue)
    Determines whether the SortedDictionary<TKey,TValue> contains an element with the specified value.
  • Remove(TKey)
    Removes the element with the specified key from the SortedDictionary<TKey,TValue>.

You can check for all properties and methods of the SortedDictionary<TKey, TValue> here:

SortedDictionary<TKey, TValue> Class

— — — — — — — — — —

1.5 Stack<T>

A stack is a Last-In, First-Out (LIFO) collection of elements where the last element that goes into the stack will be the first element that comes out.

Inserting an element into a stack is called ‘Pushing’

Deleting an element from a stack is called ‘Popping’

Pushing and popping can be performed only at the top of the stack.

The Stack<T> class requires all elements be of the same type T.

For example:

Output:

Stack<T> properties and methods:

  • Count
    Gets the number of elements contained in the Stack<T>.
  • Clear()
    Removes all objects from the Stack<T>.
  • Contains(T)
    Determines whether an element is in the Stack<T>.
  • Peek()
    Returns the object at the top of the Stack<T> without removing it.
  • Pop()
    Removes and returns the object at the top of the Stack<T>.
  • Push(T)
    Inserts an object at the top of the Stack<T>.
  • ToArray()
    Copies the Stack<T> to a new array.

You can check for all properties and methods of the Stack<T> here:

Stack<T> Class

— — — — — — — — — —

1.6 Queue<T>

A queue is a First-In, First-Out (FIFO) collection of elements where the first element that goes into a queue is also the first element that comes out.

Inserting an element into a queue is referred to as ‘Enqueue’

Deleting an element from a queue is referred to as ‘Dequeue’

The Queue<T> class requires all elements be of the same type T.

For example:

Output:

Queue<T> properties and methods:

  • Count
    Gets the number of elements contained in the Queue<T>.
  • Clear()
    Removes all objects from the Queue<T>.
  • Contains(T)
    Determines whether an element is in the Queue<T>.
  • Dequeue()
    Removes and returns the object at the beginning of the Queue<T>.
  • Enqueue(T)
    Adds an object to the end of the Queue<T>.
  • Peek()
    Returns the object at the beginning of the Queue<T> without removing it.
  • ToArray()
    Copies the Queue<T> elements to a new array.

You can check for all properties and methods of the Queue<T> here:

Queue<T> Class

— — — — — — — — — —

1.7 HashSet<T>

A hash set is a set of unique values where duplicate values are not allowed.

The HashSet<T> is a dynamic collection, means the size of the HashSet is automatically increased when the new elements are added.

Hash sets are different from other collections because they’re simply a set of values. They don’t have index positions and elements can’t be ordered.

The HashSet<T> class requires all elements be of the same type T.

For example:

Output:

HashSet<T> properties and methods:

  • Count
    Gets the number of elements that are contained in a set.
  • Add(T)
    Adds the specified element to a set.
  • Clear()
    Removes all elements from a HashSet<T> object.
  • Contains(T)
    Determines whether a HashSet<T> object contains the specified element.
  • Remove(T)
    Removes the specified element from a HashSet<T> object.
  • IsSubsetOf(IEnumerable<T>)
    Determines whether a HashSet<T> object is a subset of the specified collection.
  • IsSupersetOf(IEnumerable<T>)
    Determines whether a HashSet<T> object is a superset of the specified collection.
  • UnionWith(IEnumerable<T>)
    Modifies the current HashSet<T> object to contain all elements that are present in itself, the specified collection, or both.
  • IntersectWith(IEnumerable<T>)
    Modifies the current HashSet<T> object to contain only elements that are present in that object and in the specified collection.

You can check for all properties and methods of the HashSet<T> here:

HashSet<T> Class

— — — — — — — — — —

1.8 SortedSet<T>

A sorted set is a collection of objects that is maintained in sorted order. It is a dynamic collection, means the size of the SortedSet is automatically increased when the new elements are added.

The SortedSet<T> object maintains a sorted order without affecting performance as elements are inserted and deleted.

***Duplicate elements are not allowed. Changing the sort values of existing items is not supported and may lead to unexpected behavior.

The SortedSet<T> class requires all elements be of the same type T.

For example:

Output:

SortedSet<T> properties and methods:

  • Count
    Gets the number of elements in the SortedSet<T>.
  • Max
    Gets the maximum value in the SortedSet<T>, as defined by the comparer.
  • Min
    Gets the minimum value in the SortedSet<T>, as defined by the comparer.
  • Add(T)
    Adds an element to the set and returns a value that indicates if it was successfully added.
  • Clear()
    Removes all elements from the set.
  • Contains(T)
    Determines whether the set contains a specific element.
  • IntersectWith(IEnumerable<T>)
    Modifies the current SortedSet<T> object so that it contains only elements that are also in a specified collection.
  • IsSubsetOf(IEnumerable<T>)
    Determines whether a SortedSet<T> object is a subset of the specified collection.
  • IsSupersetOf(IEnumerable<T>)
    Determines whether a SortedSet<T> object is a superset of the specified collection.
  • UnionWith(IEnumerable<T>)
    Modifies the current SortedSet<T> object so that it contains all elements that are present in either the current object or the specified collection.
  • Remove(T)
    Removes a specified item from the SortedSet<T>.
  • Reverse()
    Returns an IEnumerable<T> that iterates over the SortedSet<T> in reverse order.

You can check for all properties and methods of the SortedSet<T> here:

SortedSet<T> Class

— — — — — — — — — —

1.9 LinkedList<T>

A linked list is a linear data structure, consists of nodes where each node contains a data field and a reference(link) to the next node in the list.

The LinkedList<T> is doubly linked, each node points forward to the ‘Next’ node and backward to the ‘Previous’ node.

If the LinkedList<T> is empty, the First and Last properties contain ‘null’.

The LinkedList<T> class requires all elements be of the same type T.

For example:

Output:

LinkedList<T> properties and methods:

  • Count
    Gets the number of nodes actually contained in the LinkedList<T>.
  • First
    Gets the first node of the LinkedList<T>.
  • Last
    Gets the last node of the LinkedList<T>.
  • AddFirst(T)
    Adds a new node containing the specified value at the start of the LinkedList<T>.
  • AddLast(T)
    Adds a new node containing the specified value at the end of the LinkedList<T>.
  • Clear()
    Removes all nodes from the LinkedList<T>.
  • Contains(T)
    Determines whether a value is in the LinkedList<T>.
  • Find(T)
    Finds the first node that contains the specified value.
  • FindLast(T)
    Finds the last node that contains the specified value.
  • Remove(T)
    Removes the first occurrence of the specified value from the LinkedList<T>.
  • RemoveFirst()
    Removes the node at the start of the LinkedList<T>.
  • RemoveLast()
    Removes the node at the end of the LinkedList<T>.

You can check for all properties and methods of the LinkedList<T> here:

LinkedList<T> Class

— — — — — — — — — —

2. Non-Generic collections

Non-Generic collections can store items that are of type ‘Object’. Since an ‘Object’ data type can refer to any data type, you run the risk of unexpected outcomes. Non-Generic collections may also be slower to access as well as execute.

The ‘System.Collections’ namespace includes the following non-generic collections:

2.1 ArrayList

— Represents an array of objects whose size is dynamically increased as required.

2.2 SortedList

— Represents a collection of key/value pairs that are sorted by the keys and are accessible by key and by index.

2.3 Stack

— Represents a last in, first out (LIFO) collection of objects.

2.4 Queue

— Represents a first in, first out (FIFO) collection of objects.

2.5 Hashtable

— Represents a collection of key/value pairs that are organized based on the hash code of the key.

2.6 BitArray

— Manages a compact array of bit values, which are represented as Booleans, where true indicates that the bit is on (1) and false indicates the bit is off (0).

To access a non-generic collection in your code, you will need to include the statement:

— — — — — — — — — — — — — — — — — —

using System.Collections;

— — — — — — — — — — — — — — — — — —

***Non-Generic collections are error prone and less performant, it’s recommended to always use ‘Generic collections’ if available.

For more details about Non-Generic Collections:

System.Collections Namespace

--

--

M. Kannika

Web Application & Blockchain Developer | Cat Lover | INTJ-A