Existe uma maneira elegante de instanciar um tipo de variável com parâmetros?

Isso não é legal:

public class MyBaseClass
{
  public MyBaseClass() {}
  public MyBaseClass(object arg) {}
}


public void ThisIsANoNo() where T : MyBaseClass
{
  T foo = new T("whoops!");
}

Para fazer isso, você tem que fazer alguma reflexão sobre o objeto de tipo para T ou você tem que usar Activator.CreateInstance. Ambos são muito desagradáveis. Existe uma maneira melhor?

0
adicionado
Visualizações: 1

4 Respostas

where T : MyBaseClass, new()

funciona apenas com construtor público sem parâmetros. além disso, de volta ao activator.CreateInstance (que realmente não é tão ruim).

0
adicionado
não de uma maneira genérica.
adicionado o autor Darren Kopp, fonte

Eu posso ver que não está funcionando.

Mas o que está impedindo você de fazer isso?

public void ThisIsANoNo() where T : MyBaseClass
{
  MyBaseClass foo = new MyBaseClass("whoops!");
}

Já que tudo vai herdar do MyBaseClass eles serão todos 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();
            ThisIsANoNo();
        }

        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() where T : MyBaseClass
        {
            MyBaseClass foo = new MyBaseClass("whoops!");
        }
    }
}
0
adicionado
T é uma extensão do MyBaseClass. Você pode criar uma instância do MyBaseClass, mas não é possível "atualizá-lo" para T, porque ele não é um T. Além disso, sua implementação ThisIsANoNo, embora tenha uma assinatura genérica, não atualiza uma instância do tipo variável.
adicionado o autor Will, fonte
é um vazio que não está retornando nada. e um elenco pode consertar isso.
adicionado o autor chrissie1, fonte
@Abe eu tentei e funciona.
adicionado o autor chrissie1, fonte
O que acontece se você tiver uma classe derivada que tenha apenas um construtor que leve 2 argumentos?
adicionado o autor Abe Heidebrecht, fonte
Esse método nunca retornará objetos do tipo T, apenas objetos do tipo MyBaseClass.
adicionado o autor Matt Howells, fonte

Não. Se você não estivesse passando parâmetros, então poderia restringir seu tipo de parâmetro para exigir um construtor sem parâmetros. Mas, se você precisar passar argumentos, você está sem sorte.

0
adicionado

Você não pode restringir T para ter uma assinatura de construtor particular diferente de um construtor vazio, mas você pode restringir T para 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() where T : MyBaseClass, new()
{
    T foo = new T().CreateFromObject("whoopee!") as T;
}

No entanto, eu sugeriria talvez usar um padrão de criação diferente, como Abstract Factory para esse cenário.

0
adicionado