Satisfying constraints
Whenever a constructed type or generic method is referenced, the supplied type arguments are checked against the type parameter constraints declared on the generic type or method (§10.1.5). For each where clause, the type argument A that corresponds to the named type parameter is checked against each constraint as follows: · If the constraint is a class type, an interface type, or a type parameter, let C represent that constraint with the supplied type arguments substituted for any type parameters that appear in the constraint. To satisfy the constraint, it must be the case that type A is convertible to type C by one of the following: o An identity conversion (§6.1.1) o An implicit reference conversion (§6.1.6) o A boxing conversion (§6.1.7), provided that type A is a non-nullable value type. o An implicit reference, boxing or type parameter conversion from a type parameter A to C. · If the constraint is the reference type constraint (class), the type A must satisfy one of the following: o A is an interface type, class type, delegate type or array type. Note that System.ValueType and System.Enum are reference types that satisfy this constraint. o A is a type parameter that is known to be a reference type (§10.1.5). · If the constraint is the value type constraint (struct), the type A must satisfy one of the following: o A is a struct type or enum type, but not a nullable type. Note that System.ValueType and System.Enum are reference types that do not satisfy this constraint. o A is a type parameter having the value type constraint (§10.1.5). · If the constraint is the constructor constraint new(), the type A must not be abstract and must have a public parameterless constructor. This is satisfied if one of the following is true: o A is a value type, since all value types have a public default constructor (§4.1.2). o A is a type parameter having the constructor constraint (§10.1.5). o A is a type parameter having the value type constraint (§10.1.5). o A is a class that is not abstract and contains an explicitly declared public constructor with no parameters. o A is not abstract and has a default constructor (§10.11.4). A compile-time error occurs if one or more of a type parameter’s constraints are not satisfied by the given type arguments. Since type parameters are not inherited, constraints are never inherited either. In the example below, D needs to specify the constraint on its type parameter T so that T satisfies the constraint imposed by the base class B<T>. In contrast, class E need not specify a constraint, because List<T> implements IEnumerable for any T. class B<T> where T: IEnumerable {...} class D<T>: B<T> where T: IEnumerable {...} class E<T>: B<List<T>> {...}
|