Generic code must work for every type of data. You can specify type constraints for a generic method or class which only allows type specified in the list of constraints.

public class GenericClass<T> where T: constraint
{
    //some code
}

To specify a type constraint, we use the where  keyword, then the name of the type parameter, a colon, then a comma separated  list of allowed types for the type parameter. For example, suppose we have a  class named Animal. We can specify a generic class  with a type constraint of Animal.

public class GenericClass<T> where T: Animal
{
    //some code
}

The type parameter T can now accept the Animal type. It can also accept any type that is a  derived class of Animal, for example, a Dogclass.

You can use the keyword struct as the type constraint to allow all value types, or class keyword, to allow all reference types. You can also use the interface keyword so it can only accept objects that implement the interface that was indicated.

public class GenericClass<T> where T: struct
{
    //some code
}

public class GenericClass<T> where T: class
{
    //some code
}

public class GenericClass<T> where T: interface
{
    //some code
}

You can also specify that the type parameter must only accept classes that has a parameterless constructor. You can do this by using new() as the constraint.

public class GenericClass<T> where T: new()
{
    //some code
}

In cases where there are multiple constraints, you must put the new() in the last position.

If there are multiple type parameters and you want to assign different constraints for each, you can follow another where statement right after the first.

public class GenericClass<T1, T2> where T1 : Animal where T2 : Plant
{
    //some code
}

If the generic class is inheriting from another class, then it must come first before the constraints.

public class GenericClass<T1, T2> : BaseClass where T1 : Animal
{
    //some code
}

One note when using type constraints, you can only use non-sealed types.  Primitive types are invalid such as intdoubleboolean, and string. Suppose we  have the following generic class:

public class GenericClass<T> where T : int
{
    //some code
}

Sealed classes cannot be inherited. If we used a sealed type such as int,  then the generic class will not be “generic” since we can only pass a single  type.