Generics express reusability with a template and placeholder types.
Generics can increase type safety and reduce casting and boxing.
A generic type declares type parameters(placeholder).
When using the generic type the placeholder will be filled in by the consumer of the generic type.
The following code defines a generic type Stack<T>.
Stack<T> declares a single type parameter T:
class Stack<T> { int position; T[] data = new T[100]; public void Push (T obj) => data[position++] = obj; public T Pop() => data[--position]; }
We can use Stack<T> as follows:
var stack = new Stack<int>(); stack.Push (5); stack.Push (10); int x = stack.Pop(); // x is 10 int y = stack.Pop(); // y is 5 Stack<int> replaces the type parameter T with the type int.
Attempting to push a string onto Stack<int> would produce a compile-time error.
Stack<T> is an open type, whereas Stack<int> is a closed type.
At runtime, all generic type instances are closed by using the placeholder types.
This means that the following statement is illegal:
var stack = new Stack<T>();