News & UpdatesProgrammingWeb programmingPartnersStore
Book Cover
Buy Now
Projects
Links

C# Tutorial – 31 – Generics III

Constraints

When defining a generic class or method, compile-time enforced restrictions can be applied on the kinds of type arguments that may be used when the class or method is instantiated. These restrictions are called constraints and are specified using the where keyword. All in all there are six kinds of constraints.

First, the type parameter can be restricted to value types by using the struct keyword.

class C<T> where T : struct {} // value type

Second, the parameter can be constrained to reference types by using the class keyword.

class D<T> where T : class {} // reference type

Third, the constraint can be a class name. This will restrict the type to either that class or one of its derived classes.

class B {}
class E<T> where T : B {} // be/derive from base class

Fourth, the type can be constrained to either be or derive from another type parameter.

class F<T, U> where T : U {} // be/derive from U

The fifth constraint is to specify an interface. This will restrict the type parameter to only those types that implement the specified interface, or that is of the interface type itself.

interface I {}
class G<T> where T : I {} // be/implement interface

Finally, the type argument can be constrained to only those types that have a public parameterless constructor.

class H<T> where T : new() {} // no parameter constructor

Multiple constraints

Multiple constraints can be applied to a type parameter by specifying them in a comma separated list. Furthermore, to constrain more than one type parameter additional where clauses can be added. Note that if either the class or the struct constraint is used it must appear first in the list. Moreover, if the parameterless constructor constraint is used it must be the last one in the list.

class J<T, U>
  where T : class, I
  where U : I, new() {}

Why to use constraints

Aside from restricting the use of a generic method or class to only certain parameter types, another reason for applying constraints is to increase the number of allowed operations and method calls supported by the constraining type. An unconstrained type may only use the System.Object methods. However, by applying a base class constraint, the accessible members of that base class also become available.

class Person
{
  public string name;
}
 
class PersonNameBox<T> where T : Person
{
  public string box;
 
  public void StorePersonName(T a)
  {
    box = a.name;
  }
}

Another example below uses the parameterless constructor constraint. This constraint enables new objects of the type parameter to be instantiated.

class MyClass<T> where T : new() {}

Note that if a class has a constraint on its type parameter, and a child of that class has a type parameter which is constrained by the base class, that constraint must also be applied to the child class’s type parameter.

class MyChild<T> : MyClass<T> where T : MyClass<T>, new() {}

If you like this tutorial please +1 it:


3 Responses

Big Country
December 16th, 2010 at 12:30  

Thank you so much… seriously.

September 26th, 2009 at 10:04  

Thanks for pointing that out. I’ve fixed the problem (forgot to encode the hashmark in C# into %23). I also went through all the other video download links and corrected similar problems. Cheers.

ajay
September 25th, 2009 at 10:28  

There is a problem in downloading the c# video tutorials…

Hoping it will be made correct soon…

Leave a Reply