Generics type define a template that contains placeholder types.
Generics can increase type safety and reduce casting and boxing.
A generic type declares type parameters which can be filled in by the consumer of the generic type.
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 = 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 type parameter T
with the type argument int
.
Stack<T>
is an open type, whereas Stack<int>
is a closed type.
A generic method declares type parameters within the signature of a method.
With generic methods, many fundamental algorithms can be implemented in a general-purpose way only.
Here is a generic method that swaps the contents of two
variables of any type T
:
static void Swap<T> (ref T a, ref T b) {
T temp = a;
a = b;
b = temp;
}
Swap<T>
can be used as follows:
int x = 5; int y = 10; Swap (ref x, ref y);
There is no need to supply type arguments to a generic method.
If there is ambiguity, generic methods can be called with the type arguments as follows:
Swap<int> (ref x, ref y);
Only methods and types can introduce type parameters.
Properties, indexers, events, fields, constructors, operators, and so on cannot declare type parameters.
The following code shows how to write an indexer that returns a generic item:
public T this [int index] {
get {
return data [index];
}
}
Constructors can take in existing type parameters, but not introduce them.