Constraining Generic types to parameterized constructors

By | July 2, 2013

Pretty cool trick I found today on StackOverflow.

I’ve often struggled with the fact that when you’re writing a generic method, while you can constrain the type of the method, you can only specify the constraint of having a constructor, and even then, only a default constructor (eg: new()); not one with parameters. Since I can constrain the type, which can in-turn constrain the constructor, it seems that I should be able to do

public T CreateMe<T>(int param) where T : MyClass
{
    return new T(param);
}

 

but alas, we can’t. At best we could new up the type-constrained object, but only if you’re constraining to a non-abstract class and not an Interface or abstract class, eg:

public T CreateMe<T>(int param) where T : MyClass
{
    return new MyClass(param);
}

 

but that won’t give us the type that we passed in as our generic.

So to re-iterate what’s posted in the StackOverflow link, the solution is to pass a Func<[param type(s)], T> creator in to the method like so:

public T CreateMe<T>(int param, Func<int, T> creator) where T : MyClass
{
    return creator(param);
}

 

Then you just use it like this:

public class MyDerivedClass : MyClass
{
    public MyDerivedClass(int param) : base(param) { }
}

var myInstance = CreateMe(1, (p) => new MyDerivedClass(p));

 

Which will spin up an instance of MyDerivedClass but pass the ‘1’ parameter in to it as the constructor specifies.

Pretty ingenious!