Generics are a template/blueprint of a Classes/Methods/Types were the actual type is defined at Runtime. Parameter types must be defined at the time of creating the instances. A Generic Class can accept any type of parameter. But sometimes it is necessary to implement a generic Class that can be instantiated with only specific types.
Constraints on generics restricts the allowable types while declaring the generic type. A compile-time error will be thrown if you attempt to instantiate a class with a type that is not allowed by a constraint.
Let's walk through with the below class, Circle
public class Circle{ }
Implementing Generic Constraints on Type Paramenters in C#
The Circle class is rewritten by implementing a generic constraints so that Circle class can be instantiated to a Value Type only.
public class Circle where T1 : struct { ... }
Below code shows the Circle class rewritten using generic constraints in such a way that it can be instantiated to a Reference Type only.
public class Circle where T1 : class { ... }
Below code shows the Circle class rewritten using generic constraints in such a way that it can be instantiated with the type argument that must have a public parameterless constructor.
public class Circle where T1 : new() { ... }
Below code shows the Circle class rewritten using generic constraints in such a way that it can be instantiated with the type argument that must be or derive from the specified base class, MyBaseClass here.
public class Circle where T1 : MyBaseClass { ... }
Below code shows the Circle class rewritten using generic constraints in such a way that it can be instantiated with the type argument that must or implement the specified interface, IMyInterface here.
public class Circle where T1 : IMyInterface { ... }
Below code shows the Circle class rewritten using generic constraints in such a way that it can be instantiated with the type argument supplied for T must be or derive from the argument supplied for U.
public class Circle where T : U { ... }