Is there an elegant way to instantiate a variable type with parameters?
-
01-07-2019 - |
Question
This isn't legal:
public class MyBaseClass
{
public MyBaseClass() {}
public MyBaseClass(object arg) {}
}
public void ThisIsANoNo<T>() where T : MyBaseClass
{
T foo = new T("whoops!");
}
In order to do this, you have to do some reflection on the type object for T or you have to use Activator.CreateInstance. Both are pretty nasty. Is there a better way?
Solution
You can't constrain T to have a particular constructor signature other than an empty constructor, but you can constrain T to have a factory method with the desired signature:
public abstract class MyBaseClass
{
protected MyBaseClass() {}
protected abstract MyBaseClass CreateFromObject(object arg);
}
public void ThisWorksButIsntGreat<T>() where T : MyBaseClass, new()
{
T foo = new T().CreateFromObject("whoopee!") as T;
}
However, I would suggest perhaps using a different creational pattern such as Abstract Factory for this scenario.
OTHER TIPS
Nope. If you weren't passing in parameters, then you could constrain your type param to require a parameterless constructor. But, if you need to pass arguments you are out of luck.
where T : MyBaseClass, new()
only works w/ parameterless public constructor. beyond that, back to activator.CreateInstance (which really isn't THAT bad).
I can see that not working.
But what is stopping you from doing this?
public void ThisIsANoNo<T>() where T : MyBaseClass
{
MyBaseClass foo = new MyBaseClass("whoops!");
}
Since everything is going to inherit from MyBaseClass they will al be MyBaseClass, right?
I tried it and this works.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
ThisIsANoNo<MyClass>();
ThisIsANoNo<MyBaseClass>();
}
public class MyBaseClass
{
public MyBaseClass() { }
public MyBaseClass(object arg) { }
}
public class MyClass :MyBaseClass
{
public MyClass() { }
public MyClass(object arg, Object arg2) { }
}
public static void ThisIsANoNo<T>() where T : MyBaseClass
{
MyBaseClass foo = new MyBaseClass("whoops!");
}
}
}