Generics
C# has two separate mechanisms for writing code that is reusable across different types: inheritance and generics. Whereas inheritance expresses reusability with a base type, generics express reusability with a “template” that contains “placeholder” types. Generics, when compared to inheritance, can increase type safety and reduce casting and boxing.
Generic Types
A generic type declares type
parameters—placeholder types to be filled in by the consumer of the generic type,
which supplies the type arguments. Here is a
generic type, Stack<T>,
designed to stack instances of type T. Stack<T> declares a single type parameter T:
public class Stack<T>{ int position;T[] data = newT[100]; public void Push (Tobj) { data[position++] = obj; } publicTPop() { return data[--position]; } }
We can use Stack<T> as
follows:
Stack<int>stack = new Stack<int>(); stack.Push(5); stack.Push(10); int x = stack.Pop(); // x is 10 int y = stack.Pop(); // y is 5
Note
Notice that no downcasts are required in the last two lines,
avoiding the possibility of a runtime error and eliminating the
overhead of boxing/unboxing. This makes our generic stack superior to
a nongeneric stack that uses object
in place of T (see The object Type for an example).
Stack<int> fills in the
type parameter T with the type
argument int, implicitly creating a
type on the fly (the synthesis occurs at runtime). Stack<int> effectively has the following definition (substitutions appear in bold, with the class name hashed out to avoid ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access