Generics
A generic type or method works with any type, decided when it's used, without giving up type safety or duplicating code.
class Stack<T>
{
private List<T> items = new List<T>();
public void Push(T item) => items.Add(item);
public T Pop()
{
T last = items[^1];
items.RemoveAt(items.Count - 1);
return last;
}
}
var numbers = new Stack<int>();
numbers.Push(5);
numbers.Push(10);
Console.WriteLine(numbers.Pop()); // 10
var names = new Stack<string>();
names.Push("Ada");
The pieces
<T>is a type parameter, a placeholder that gets filled in with a real type (int,string, ...) when the class or method is used.Stack<int>andStack<string>are both backed by the sameStack<T>code, but the compiler enforces that aStack<int>only ever holdsints.- Generic methods work the same way:
T Max<T>(T a, T b) where T : IComparable<T>. where T : SomeConstraintrestricts whatTcan be, e.g.where T : class(reference types only) orwhere T : IDamageable.
Why not just use object?
A non-generic collection typed as object would compile but let you push mismatched types, and would need a cast (with a runtime risk) every time you read a value out. Generics catch that mistake at compile time instead.