In my previous article I have discussed about the generics in C#. Here in this article I will discuss about the various generics constraints and how they can be useful. Lets see all the generic constraints provided by C#.
Base class Generic Constraint
In this constraint we should be able to provide the generic type parameter which is derived from the class provided in constraint.
public class A { } public class Base { } public class Derived: Base { } public class Clientwhere T:Base { }
In the above code I have written a Client class which expects a generic type parameter of type “Base”. I have constrained this type parameter to be of the Base class type. I can also provide all the derived types also as the generic parameter while creating “Client” instance.
As we can see in the above figure, the first two lines of the code are perfectly valid and are compiled. But if we are providing a generic type parameter as “A” we are getting a compile time error. And it is due to the reason that class A is no where related to the “Base” class.
Interface Generic Constraint
In place of constraining by base class as shown in the previous part. We can also constrain a generic type parameter by interface as shown below.
public interface IMyInterface { } public class MyClass: IMyInterface { } public class MyClassWithoutInterface { } public class Clientwhere T:IMyInterface { }
In the above code if I am providing generic type parameter derived from the interface IMyInterface, it would be perfectly fine. But if my type parameter is not derived from IMyInterface, we will get a compile time error.
Reference Type generic constraint
We can put a reference type constraint on generic type parameter as shown below.
public class Clientwhere T:class { }
And please check the figure below.
If we creating an instance of “Client” class by using string as type parameter, it works fine. Since string is a reference type. But if we are using “int” as type parameter we should get a compile time error.
We can also use any user defined type in this case.
Value Type Generic Constraint
Similarly we can use the value type as generic constraints. Lets have a look at the code below.
public class Clientwhere T:struct { }
In this case I am expecting my generic type parameter to be any value type. Lets have a look at the result in the below figure.
In this case we are getting a compile time error for the string but not for int.
If we provide a nullable value type in this case we should get a compile time error.
Parameter less class Constructor
This is the constraint in which we should provide a type as generic parameter which should contain a parameter less constructor.
The above figure is self descriptive in this case. We cannot use this constraint with the private constructor. This generic type constraint I can use to create a new instance of the type parameter as shown in the code below.
public class Clientwhere T:new() { public T CreateNew() { return new T(); } }
If we remove the type constraint from the class we will not be able to create a new instance of type parameter. Please check the figure below.
Multiple Generic Constraints for Single Class
We can also use all the generic constraints discussed till now for a single class as shown in the code below.
public class Clientwhere T: MyClass, IMyClass, new() { public T CreateNew() { return new T(); } }
In the code I have used all the generic constraints discussed till not for a single type parameter. It means that while creating an instance of “Client” class I should provide a type parameter which should adhere to all the generic constraints.
Conclusion:
In this article I have discussed all the generic type constraints present in C#. These are the constraints which we should keep in mind and they can come as very handy while working on the live projects. If we are not sure about generic constraints then our knowledge about generics would be incomplete.
Leave a Reply