15
Lesson 15 of 35 ยท OOP

Generics

Generics let you write classes, interfaces, and methods that work with any type while maintaining compile-time type safety. They eliminate the need for casting and reduce code duplication.

Generic Classes

Add a type parameter <T> to a class declaration. You can constrain T with the where clause.

Generic stack GenericStack.cs
public class Stack
{
    private readonly List _items = [];

    public void Push(T item) => _items.Add(item);

    public T Pop()
    {
        if (_items.Count == 0) throw new InvalidOperationException("Stack empty");
        T item = _items[^1];
        _items.RemoveAt(_items.Count - 1);
        return item;
    }

    public T Peek() => _items[^1];
    public int Count => _items.Count;
}

var s = new Stack();
s.Push(10); s.Push(20); s.Push(30);
Console.WriteLine(s.Pop()); // 30

Generic Methods & Constraints

A method can have its own type parameters. Constraints restrict what types are valid: where T : class (reference types), where T : struct (value types), where T : new() (has parameterless constructor), where T : ISomeInterface.

Generic method GenMethod.cs
static T Max(T a, T b) where T : IComparable
    => a.CompareTo(b) >= 0 ? a : b;

Console.WriteLine(Max(3, 7));       // 7
Console.WriteLine(Max("apple", "banana")); // banana
Console.WriteLine(Max(3.14, 2.72)); // 3.14