where (generic type constraint) (C# Reference)
The where
clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function. Constraints can specify interfaces, base classes, or require a generic type to be a reference, value or unmanaged type. They declare capabilities that the type argument must possess.
For example, you can declare a generic class, MyGenericClass
, such that the type parameter T
implements the IComparable<T> interface:
public class AGenericClass<T> where T : IComparable<T> { }
Note
For more information on the where clause in a query expression, see where clause.
The where
clause can also include a base class constraint. The base class constraint states that a type to be used as a type argument for that generic type has the specified class as a base class (or is that base class) to be used as a type argument for that generic type. If the base class constraint is used, it must appear before any other constraints on that type parameter. Some types are disallowed as a base class constraint: Object, Array, and ValueType. Prior to C# 7.3, Enum, Delegate, and MulticastDelegate were also disallowed as base class constraints. The following example shows the types that can now be specified as a base class:
public class UsingEnum<T> where T : System.Enum { }
public class UsingDelegate<T> where T : System.Delegate { }
public class Multicaster<T> where T : System.MulticastDelegate { }
The where
clause can specify that the type is a class
or a struct
. The struct
constraint removes the need to specify a base class constraint of System.ValueType
. The System.ValueType
type may not be used as a base class constraint. The following example shows both the class
and struct
constraints:
class MyClass<T, U>
where T : class
where U : struct
{ }
The where
clause may also include an unmanaged
constraint. The unmanaged
constraint limits the type parameter to types known as unmanaged types. An unmanaged type is a type that isn't a reference type and doesn't contain reference type fields at any level of nesting. The unmanaged
constraint makes it easier to write low-level interop code in C#. This constraint enables reusable routines across all unmanaged types. The unmanaged
constraint can't be combined with the class
or struct
constraint. The unmanaged
constraint enforces that the type must be a struct
:
class UnManagedWrapper<T>
where T : unmanaged
{ }
The where
clause may also include a constructor constraint, new()
. That constraint makes it possible to create an instance of a type parameter using the new
operator. The new() Constraint lets the compiler know that any type argument supplied must have an accessible parameterless--or default-- constructor. For example:
public class MyGenericClass<T> where T : IComparable<T>, new()
{
// The following line is not possible without new() constraint:
T item = new T();
}
The new()
constraint appears last in the where
clause. The new()
constraint can't be combined with the struct
or unmanaged
constraints. All types satisfying those constraints must have an accessible parameterless constructor, making the new()
constraint redundant.
With multiple type parameters, use one where
clause for each type parameter, for example:
public interface IMyInterface { }
namespace CodeExample
{
class Dictionary<TKey, TVal>
where TKey : IComparable<TKey>
where TVal : IMyInterface
{
public void Add(TKey key, TVal val) { }
}
}
You can also attach constraints to type parameters of generic methods, as shown in the following example:
public void MyMethod<T>(T t) where T : IMyInterface { }
Notice that the syntax to describe type parameter constraints on delegates is the same as that of methods:
delegate T MyDelegate<T>() where T : new();
For information on generic delegates, see Generic Delegates.
For details on the syntax and use of constraints, see Constraints on Type Parameters.
C# language specification
For more information, see the C# Language Specification. The language specification is the definitive source for C# syntax and usage.
See also
Feedback
We'd love to hear your thoughts. Choose the type you'd like to provide:
Our feedback system is built on GitHub Issues. Read more on our blog.
Loading feedback...