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 (T
obj) { data[position++] = obj; } publicT
Pop() { 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 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 ...
Get C# 4.0 Pocket Reference, 3rd Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.