Existe uma maneira elegante de instanciar um tipo variável com parâmetros?
-
01-07-2019 - |
Pergunta
Isto não é legal:
public class MyBaseClass
{
public MyBaseClass() {}
public MyBaseClass(object arg) {}
}
public void ThisIsANoNo<T>() where T : MyBaseClass
{
T foo = new T("whoops!");
}
A fim de fazer isso, você tem que fazer alguma reflexão sobre o objeto tipo para T ou você tem que usar Activator.CreateInstance. Ambos são bastante desagradável. Existe uma maneira melhor?
Solução
Você não pode restringir T ter uma assinatura de construtor especial que não seja um construtor vazio, mas você pode restringir T ter um método de fábrica com a assinatura desejada:
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;
}
No entanto, gostaria de sugerir talvez usando um padrão criacional diferente, como o Abstract Factory para este cenário.
Outras dicas
Não. Se você não estivesse passando em parâmetros, então você pode restringir o seu tipo de param de exigir um construtor sem parâmetros. Mas, se você precisa passar argumentos que você está fora de sorte.
where T : MyBaseClass, new()
só funciona w / parâmetros construtor público. além disso, de volta para Activator.CreateInstance (que realmente não é tão ruim).
Eu posso ver que não funciona.
Mas o que é que você parar de fazer isso?
public void ThisIsANoNo<T>() where T : MyBaseClass
{
MyBaseClass foo = new MyBaseClass("whoops!");
}
Uma vez que tudo está indo para herdar de MyBaseClass eles vão al ser MyBaseClass, certo?
Eu tentei e isso funciona.
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!");
}
}
}