Generic methods
In some cases, a type parameter is not needed for an entire class, but only when calling a particular method. Often, this occurs when creating a method that takes a generic type as a parameter. For example, when using the geneic Stack, we might often find ourselves pushing multiple values in a row onto a stack, and decide to write a method to do so in a single call. If we are only using a single kind of Stack, say Stack<int>, writing such a method is easy:
static void PushMultiple(Stack<int> s, params int[] values{
foreach (int v in values) {
s.Push(v);
}
}
We can use this method to push multiple int values onto a Stack<int>:
Stack<int> s = new Stack<int>();
PushMultiple(s, 1, 2, 3, 4);
However, the method above only works with one particular constructed type: Stack<int>. While we can easily write similar code for other constructed Stack types, we would like to write a single method that can work with any Stack, no matter what type argument was used.
We do this by writing a generic method. Like a generic class declaration, a generic method is written with type parameters enclosed in angle brackets. With a generic method, the type parameters are written immediately after the method name, and can be used within the parameter list, return type, and body of the method. A generic PushMultiple method would look like this:
static void PushMultiple<ItemType>(Stack<ItemType> s, params ItemType[] values)
{
foreach (ItemType v in values) {
s.Push(v);
}
}
Using this generic method, we can now push multiple items onto a Stack of any kind. Furthermore, the compiler type checking will ensure that the pushed items have the correct type for the kind of Stack being used. When calling a generic method, we place type arguments to the method in angle brackets. The generic PushMultiple method can be called this way:
Stack<int> s = new Stack<int>();
PushMultiple<int>(s, 1, 2, 3, 4);
This generic PushMultiple method is much better than the previous version, since it works on any kind of Stack. However, it appears to be less convenient to call, since the desired ItemType shall be supplied as a type argument to the method. In many cases, however, the compiler can deduce the correct type argument from the other arguments passed to the method, using a process called type inferencing. In the example above, since the first regular argument is of type Stack<int>, and the subsequent arguments are of type int, the compiler can reason that the type parameter shall also be int. Thus, the generic PushMultiple method can be called without specifying the type parameter:
Stack<int> s = new Stack<int>();
PushMultiple(s, 1, 2, 3, 4);