Lesson 19 of 30
Generics and Generic Collections
C# in Visual Studio 2026 — a hands-on guide for developers at every level.
Why Generics?
Generics let you write type-safe, reusable code without knowing the concrete type at compile time. You avoid boxing, casting, and runtime errors.
// Generic stack
public class Stack<T>
{
private readonly List<T> _items = [];
public void Push(T item) => _items.Add(item);
public T Pop()
{
if (_items.Count == 0) throw new InvalidOperationException("Empty stack");
T top = _items[^1];
_items.RemoveAt(_items.Count - 1);
return top;
}
public int Count => _items.Count;
}
var stack = new Stack<int>();
stack.Push(1); stack.Push(2); stack.Push(3);
Console.WriteLine(stack.Pop()); // 3
Generic Constraints
// T must implement IComparable<T>
static T Max<T>(T a, T b) where T : IComparable<T>
=> a.CompareTo(b) > 0 ? a : b;
Console.WriteLine(Max(3, 7)); // 7
Console.WriteLine(Max("apple", "zebra")); // zebra
Built-in Generic Collections
| Type | Description |
|---|---|
List<T> | Resizable ordered list |
Dictionary<K,V> | Key-value pairs |
Queue<T> | FIFO queue |
Stack<T> | LIFO stack |
HashSet<T> | Unique elements, fast lookup |
SortedDictionary<K,V> | Key-value pairs sorted by key |