Generics refer to the usage of type parameters, which provide a way to design code templates
that can operate with different data types. Specifically, we can create generic methods,
classes, interfaces, delegates, and events.
First, let’s look at generic methods. In this example we have a method that swaps two
integer arguments. To make this into a generic method that can work with any type we first
need to add a type parameter after the method’s name enclosed between angle brackets (<>). The
naming convention for type parameters is that they should to start with a capital T and
then have each word that describes the parameter initially capitalized. In cases such as this
however, where a descriptive name would not add much value, its common to simply name
the parameter with a capital T. Either way, this type parameter can now be used as any
other type inside the method and so the second thing we need to do to complete the generic
method is to replace the data type that we want to be made generic with our type parameter.
The generic method is now finished. To call it we need to specify the desired type parameter
in angle brackets before the method parameters. In this case, we may also call the generic
method as if it was a regular method without specifying the type parameter. This is because
the compiler can automatically determine the type since the generic method's arguments
uses the type parameter. However, if this was not the case, or if we want to use another
type parameter than the one the compiler would select, we would then need to explicitly specify
it.
Whenever a generic is called for the first time during run-time a specialized version
of the generic will be instantiated that has every occurrence of the type parameter substituted
with the specified type. And it is this generated method that will be called from this line.
Calling the generic method again with the same type parameter will reuse this instantiated
method. And calling the generic with a new type parameter will cause another specialized
method to also be instantiated.
A generic can be defined to accept more than one type parameter just by adding more of
them between the angle brackets. Generic methods can also be overloaded based on the number
of type parameters that they define.
When using generics one issue that may arise is how to assign a default value to a type
parameter since this value depends on the type. The solution is to use the default keyword
followed by the type parameter enclosed in parenthesis. This expression will return the
default value no matter which type parameter is used.