English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

C# Generic Constraints

C# allows you to use constraints to limit the types that client code can specify when instantiating generic types. If you try to instantiate a generic type with a type that is not allowed by the specified constraints, a compile-time error will occur.

You can use the where clause after the generic type name to specify one or more constraints on the generic type.

GenericTypeName<T> where T : contraint1, constraint2

The following example demonstrates a generic class with constraints on reference types when instantiating a generic class.

class DataStore<T> where T : class
{
    public T Data { get; set; }
{}

Above, we applied class constraints, which means that only reference types can be passed as arguments when creating DataStore class objects. Therefore, you can pass reference types such as classes, interfaces, delegates, or array types. Passing value types will result in a compile-time error, so we cannot pass primitive data types or struct types.

DataStore<string> store = new DataStore<string>(); // Valid
DataStore<MyClass> store = new DataStore<MyClass>(); // Valid
DataStore<IMyInterface> store = new DataStore<IMyInterface>(); // Valid
DataStore<IEnumerable> store = new DataStore<IMyInterface>(); // Valid
DataStore<ArrayList> store = new DataStore<ArrayList>(); // Valid
//DataStore<int> store = new DataStore<int>(); // Compile-time Error

The following table lists the types of generic constraints.

ConstraintsDescription
class

The type parameter must be any class, interface, delegate, or array type.

class?

The type parameter must be a nullable or non-nullable class, interface, delegate, or array type.

struct

The type parameter must be a non-empty value type, such as the primitive data types int, char, bool, float, etc.

new()

The type parameter must be a reference type with a public no-argument constructor. It cannot be combined with struct constraint and unmanaged constraint.

notnull

from C# 8.0 and later, type parameters can be non-nullable reference types or value types. Otherwise, the compiler will generate a warning instead of an error.

unmanaged

The type parameter must be a non-nullable unmanaged type.

base class name

The type parameter must be or derive from the specified base class. It is not allowed to use Object, Array, or ValueType as base class constraints.

In C# 7.3Prior to version 8.0, Enum, Delegate, MulticastDelegate were not allowed as base class constraints.

<base class name>?

The type parameter must be or derive from the specified nullable or non-nullable base class

<interface name>

The type parameter must be or implement the specified interface.

<interface name>?

The type parameter must be or implement the specified interface. It can be a nullable reference type, a non-nullable reference type, or a value type

where T: U

The type parameter provided for T must be or derive from the parameter provided for U.

where T : struct

The following example demonstrates how to restrict the type parameter to a value type struct constraint that cannot be null.

class DataStore<T> where T : struct
{
    public T Data { get; set; }
{}
DataStore<int> store = new DataStore<int>(); // Valid
DataStore<char> store = new DataStore<char>(); // Valid
DataStore<MyStruct> store = new DataStore<MyStruct>(); // Valid
//DataStore<string> store = new DataStore<string>(); // Compile-time Error 
//DataStore<IMyInterface> store = new DataStore<IMyInterface>(); // Compile-time Error 
//DataStore<ArrayList> store = new DataStore<ArrayList>(); // Compile-time Error

where T: Base class

The following example demonstrates how to restrict the type parameter to the base class of a derived class from a specified class, abstract class, or interface.

class DataStore<T> where T : IEnumerable
{
    public T Data { get; set; }
{}
DataStore<ArrayList> store = new DataStore<ArrayList>(); // Valid
DataStore<List> store = new DataStore<List>(); // Valid
//DataStore<string> store = new DataStore<string>(); // Compile-time Error 
//DataStore<int> store = new DataStore<int>(); // Compile-time Error 
//DataStore<IMyInterface> store = new DataStore<IMyInterface>(); // Compile-time Error 
//DataStore<MyClass> store = new DataStore<MyClass>(); // Compile-time Error