A number of of times in my career, I have found my work frustrated by the sometimes arbitrary limitations placed on generics in C#. The addition of generic covariance and contravariance was a big step forward in that regard. Still, there remain many frustrating limitations. The fact that you can’t use Enum or Delegate as a generic constraint can be worked around using packages like ExtraConstrains.Fody or UnconstrainedMelody. However, extension methods also provide a little known way of working around some limitations. It is so little known that I couldn’t find a blog post that discussed the technique while working on this one (though I think I recall reading one once). Indeed, these over 2 year old stockoverflow.com questions “Is it possible to constrain a C# generic method type parameter as ‘assignable from’ the containing class’ type parameter?” and “Constrain type parameter to a base type” had no answers showing this approach until I answered them while writing this.

An Example

Imagine we create a generic pair class that we will use any time we want to deal with a pair of values that may or may not be of the same type.

public class Pair < TFirst , TSecond > { public TFirst First ; public TSecond Second ; public Pair ( TFirst first , TSecond second ) { First = first ; Second = second ; } }

Then we might find that we sometimes want to know if the two values are in order. So we imagine we could write a method to tell us if that is the case.

public bool InOrder () where TFirst : IComparable < TSecond > // Doesn't compile { return First . CompareTo ( Second ) <= 0 ; }

We’ll quickly realize that this code doesn’t compile at all, because we aren’t allowed to add generic constraints to a non-generic method.

Another time, we think it would be useful to be able to apply a function to both values. So we attempt to write the apply method. We will need to constrain the type of the function to accept both the first and second value.

public Pair < TResult , TResult > Apply < TValue , TResult >( Func < TValue , TResult > func ) where TFirst : TValue // Doesn't compile where TSecond : TValue // Doesn't compile { return new Pair < TResult , TResult >( func ( First ), func ( Second )); }

But again, we are thwarted by the compiler. In both cases, the underlying issue is that you can’t further constrain the type parameter of a class from a method.

Lastly, we might imagine it would be nice to have a method that swapped the first and second value. Of course, that only makes sense when they have the same type. It is very difficult to envision how one might write this method as there is no generic constraint for type equality in C#.