← Back to Article List         
Generic Collections in C# – Examples

Generic Collections in C# – Examples

Published on 22 Oct 2026     4 min read C#
Collections in C#
 

Generic Collections in C# – Examples

Generic collections are type-safe collections available in the System.Collections.Generic namespace. They store and manage multiple values of a specified data type.

1. List<T> – Dynamic Array

Stores elements in order, allows duplicates, and supports index-based access.


List<int> numbers = new List<int> { 10, 20, 30 };

numbers.Add(40);
numbers.Remove(20);

foreach (int number in numbers)
{
    Console.WriteLine(number);
}

// Output: 10, 30, 40

Key Points: Dynamic size, allows duplicates, maintains insertion order.

2. Dictionary<TKey, TValue> – Key-Value Pairs

Stores data as key-value pairs. Keys must be unique.


Dictionary<int, string> employees = new()
{
    { 101, "John" },
    { 102, "David" },
    { 103, "Peter" }
};

employees.Add(104, "Sam");

Console.WriteLine(employees[102]);

foreach (var emp in employees)
{
    Console.WriteLine($"{emp.Key} - {emp.Value}");
}

// Output: David
// 101 - John
// 102 - David
// 103 - Peter
// 104 - Sam

Key Points: Unique keys, fast lookup, values can be duplicated.

3. HashSet<T> – Unique Elements

Stores only unique values. Duplicate values are automatically ignored.


HashSet<int> numbers = new() { 10, 20, 30 };

numbers.Add(20);
numbers.Add(40);

foreach (int number in numbers)
{
    Console.WriteLine(number);
}

// Elements: 10, 20, 30, 40
// Order is not guaranteed

Key Points: No duplicates, fast membership checks, no guaranteed ordering.

4. Stack<T> – LIFO

Stack follows Last In, First Out (LIFO). The last inserted element is removed first.


Stack<string> names = new();

names.Push("John");
names.Push("David");
names.Push("Peter");

Console.WriteLine(names.Pop());  // Peter
Console.WriteLine(names.Peek()); // David
Console.WriteLine(names.Count);  // 2

Key Points: Push() adds, Pop() removes, Peek() reads the top element without removing it.

5. Queue<T> – FIFO

Queue follows First In, First Out (FIFO). The first inserted element is removed first.


Queue<string> names = new();

names.Enqueue("John");
names.Enqueue("David");
names.Enqueue("Peter");

Console.WriteLine(names.Dequeue()); // John
Console.WriteLine(names.Peek());    // David
Console.WriteLine(names.Count);     // 2

Key Points: Enqueue() adds, Dequeue() removes, Peek() reads the front element.

6. LinkedList<T> – Doubly Linked List

Stores elements in nodes linked to their previous and next nodes.


LinkedList<int> numbers = new();

numbers.AddLast(20);
numbers.AddFirst(10);
numbers.AddLast(30);

numbers.Remove(20);

foreach (int number in numbers)
{
    Console.WriteLine(number);
}

// Output: 10, 30

Key Points: Efficient insertion and deletion at known nodes, no index-based access.

7. SortedDictionary<TKey, TValue> – Sorted Keys

Stores key-value pairs automatically sorted by key.


SortedDictionary<int, string> students = new()
{
    { 3, "Peter" },
    { 1, "John" },
    { 2, "David" }
};

foreach (var student in students)
{
    Console.WriteLine($"{student.Key} - {student.Value}");
}

// Output:
// 1 - John
// 2 - David
// 3 - Peter

Key Points: Unique keys, sorted by key, typically slower lookup than Dictionary<TKey, TValue>.

8. SortedSet<T> – Sorted Unique Values

Stores unique elements in sorted order.


SortedSet<int> numbers = new() { 50, 10, 30, 20 };

numbers.Add(10);
numbers.Add(40);

foreach (int number in numbers)
{
    Console.WriteLine(number);
}

// Output: 10, 20, 30, 40, 50

Key Points: Unique values, automatically sorted, supports range operations.

Generic Collections – Quick Comparison

Collection

Duplicates

Ordering

Best Use

List<T>

Yes

Insertion order

Dynamic lists

Dictionary<K,V>

Values only

Not guaranteed

Key-value lookup

HashSet<T>

No

Not guaranteed

Unique values

Stack<T>

Yes

LIFO

Undo operations

Queue<T>

Yes

FIFO

Task processing

LinkedList<T>

Yes

Node order

Frequent node insertion/removal

SortedDictionary<K,V>

Values only

Sorted keys

Sorted key-value data

SortedSet<T>

No

Sorted

Unique sorted values

Important Interview Questions

1. List vs Array? Array has a fixed length. List<T> grows dynamically and provides methods such as Add(), Remove() and Contains().

2. List vs HashSet? List<T> allows duplicates and index-based access. HashSet<T> stores unique values and provides fast membership checks.

3. Dictionary vs SortedDictionary? Dictionary<TKey,TValue> uses hashing for fast lookup. SortedDictionary<TKey,TValue> maintains keys in sorted order.

4. Stack vs Queue? Stack follows LIFO; Queue follows FIFO.

5. Which generic collection is best for searching? Dictionary<TKey,TValue> for key-based lookup and HashSet<T> for checking whether a value exists. Both provide average O(1) lookup.

6. Are generic collections thread-safe? Most generic collections are not thread-safe for concurrent modifications. Use collections such as ConcurrentDictionary<TKey,TValue> or ConcurrentQueue<T> when appropriate.

7. Why use generic collections instead of non-generic collections? Generic collections provide compile-time type safety, reduce casting, and avoid boxing for value types in many common scenarios.