Mar 23

Generics and secondary constraints

Posted in Basics C# CLR      Comments Off on Generics and secondary constraints

Besides primary constraints, you can also constrain a generic type parameter through secondary constraints. Unlike primary constraints, you can apply zero or more secondary constraints to a generic type argument. Interfaces constraints are the most common kind of secondary constraints you’ll apply in your code. They allow the compiler to ensure that a generic type argument can only be replaced by a type which implements the interface specified by the constraint. If you want, you can specify several interface constraints. In these cases, you can only replace the generic type argument by a concrete type which implements all those interfaces. The next snippet illustrates the use of this kind of constraint:

public interface IDoSomething{}
public interface IDoSomethingElse{}
public class DoEverything:IDoSomething,IDoSomethingElse {
public class DoOneThing:IDoSomething {
public class MyGeneric<T> where T:IDoSomething, IDoSomethingElse {

And here’s some code that instantiates the class:

var aux1 = new MyGeneric<DoEverything>();//ok!
var aux2 = new MyGeneric<DoOneThing>();//oops

Besides interfaces, there’s another kind of secondary constraint, which is known as naked type constraint. This secondary constraint allows you to specify the existence of a relationship between two generic type arguments. Here’s a quick example:

public class AnotherGeneric<T, TBase> where T:TBase {

And here’s some code that shows how you can (and can’t instantiate it):

public class A{}
public class B:A{}
var ok = new AnotherGeneric<B, A>();
var oopss = new AnotherGeneric<A, B>();

ok compiles without an error, but that doesn’t happen with oopss because the compiler knows it can’t convert from A to B (though it knows that it can convert from B to A) .

And I guess that’s it for now. Stay tuned for more.