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 generic parameters—placeholder types to be filled in by the consumer of the generic type, who will supply the generic arguments. Here is a generic type Stack<T>, designed to stack instances of type T. Stack<T> declares a single generic parameter T:

	public class Stack<T>
	{
	  int position;
	  T[] data = new T[100];
	  public void Push (T  obj) { data[position++] = obj;  }
	  public T 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

Stack<int> fills in the generic parameter T with the generic 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 confusion):

	public class ###
	{
	  int position;
	  int[] data;
	  public void Push (int obj) { data[position++] = obj; }
	  public int Pop()           { return data[--position];}
	}

Technically, we say that Stack<T> is an open type, whereas Stack<int> is a closed type. You ...

Get C# 3.0 Pocket Reference, 2nd 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.