In my previous post, I explained about Generics. C# also provides generic methods. We can create a method that defers the parameter data type until the method is called. These parameters are called type parameters, which means we can pass the actual data type later.
Below is an example of the generic method.
static void Swap<T>(ref T input1, ref T input2)
{
T temp = default(T);
temp = input2;
input2 = input1;
input1 = temp;
}
static void Main(string[] args)
{
int first = 4;
int second = 5;
Swap<int>(ref first, ref second);
}
In the above example, we have declared a Swap generic method. In that method, we have declared a type argument after the method name, <T>. T is the type of argument. In the main method, we pass the Swap method with an <int> type argument. That means we can only pass parameters of int types. We declared two integer parameters and passed them into the swap method.
Generic Methods and Generic Classes
The generic method type parameter hides the type parameter of generic classes. CLR will not issue any warnings or errors when we use the same type parameter name with both generic methods and generic classes.
Below is an example:
public class Helper<T>
{
public void Method<T>(T input)
{
Console.WriteLine(input); //Result Hello
}
}
class Program
{
static void Main(string[] args)
{
Helper<int> helper = new Helper<int>();
helper.Method<string>("Hello");
 //Result:
 // Hello
}
}
In the above generic method example, we have taken the same type parameter name that is used by the generic class. In the main method, we have passed the <int> type argument in the Helper class. In the method, we have passed the <string> argument.
Generic Overloaded Methods
C# allows you to define generic overloaded methods with many type parameters.
Below is an example:
static void Swap<T>(T input) { }
static void Swap<T, U>(T input, U input2) { }
static void Swap<T, U, W>(T input, U input2, W input3) { }
Generic Methods Constraints
Constraints are validations on type arguments, which is the type of parameter we can pass in the generic method. Generic classes and generic methods follow the same constraints.
There are six types of constraints.
- where T : struct: type argument must be a value type
- where T : class-type argument must be a reference type
- where T: new(): type argument must have a public parameterless constructor.
- where T: <base class> – Type argument must inherit from <base class> class.
- where T : <interface> – Type argument must implement from <interface> interface.
- where T: U:Â There are two types of arguments, T and U. T must be inherited from U.
Below is an example of the usage of the above constraints in generic methods.
static void Swap<T>(ref T input1, ref T input2) where T : struct { }
static void Swap<T>(ref T input1, ref T input2) where T : class { }
static void Swap<T>(ref T input1, ref T input2) where T : new() { }
static void Swap<T>(ref T input1, ref T input2) where T : BaseEmployee { }
static void Swap<T>(ref T input1, ref T input2) where T : IEmployee { }
static void Swap<T, U>(ref T input1, ref U input2) where T : U { }
Final Words
Generic classes and generic methods are great tools for C# programmers. With both, we can create generic classes and methods that can work with any data type.