C# Generic Constraints
In this chapter you will learn:
- What are Generic Constraints
- Type of constraints
- Example for Generic Constraints
- Note for Generic Constraints
- Example for base class constraint or interface constraint
- Example for class constraint and struct constraint
- Example for parameterless constructor constraint
- Example for naked type constraint
Description
By default, a type parameter can be substituted with any type whatsoever. Constraints can be applied to a type parameter to require more specific type arguments.
Type of constraints
These are the possible constraints:
where T : base-class // Base class constraint
where T : interface // Interface constraint
where T : class // Reference-type constraint
where T : struct // Value-type constraint (excludes Nullable types)
where T : new() // Parameterless constructor constraint
where U : T // Naked type constraint
//from ww w. j a v a2 s .c o m
Example
In the following example, GenericClass<T,U> requires T to derive from MyClass and implement MyInterface, and requires U to provide a parameterless constructor:
class MyClass {}
interface MyInterface {}
//from w w w .j av a 2 s.com
class GenericClass<T> where T : MyClass, MyInterface
where U : new()
{}
Note
Constraints can be applied wherever type parameters are defined, in both methods and type definitions.
Example 2
A base class constraint or interface constraint specifies that the type parameter must subclass or implement a particular class or interface. This allows instances of that type to be implicitly cast to that class or interface.
For example, suppose we want to write a generic Max method, which returns the maximum of two values.
We can
take advantage of the generic interface defined in the framework
called IComparable<T>
:
public interface IComparable<T> // Simplified version of interface
{
int CompareTo (T other);
}
CompareTo
returns a positive number if other is
greater than this. Using this interface
as a constraint, we can write a Max method as follows:
static T Max <T> (T a, T b) where T : IComparable<T>
{
return a.CompareTo (b) > 0 ? a : b;
}
The Max
method can accept arguments of any type implementing
IComparable<T>
which includes most built-in types such as int and string:
int z = Max (5, 10); // 10
string last = Max ("ant", "zoo"); // zoo
Example 3
The class constraint and struct constraint specify that T must be a reference type or (non-nullable) value type.
A great example of the struct constraint is the System.Nullable<T> struct:
struct Nullable<T> where T : struct {...}
Example 4
The parameterless constructor constraint requires T to have a public parameterless constructor. If this constraint is defined, you can call new() on T:
static void Initialize<T> (T[] array) where T : new()
{//from w ww .j a v a 2s . c o m
for (int i = 0; i < array.Length; i++)
array[i] = new T();
}
Example 5
The naked type constraint requires one type parameter to derive from another type parameter.
In this example, the method FilteredStack returns another Stack, containing only the subset of elements where the type parameter T is of the type parameter U:
class Stack<T>
{
Stack<U> FilteredStack<U>() where U : T {...}
}
Next chapter...
What you will learn in the next chapter: