¿Existe una forma elegante de crear una instancia de un tipo de variable con parámetros?

StackOverflow https://stackoverflow.com/questions/96541

  •  01-07-2019
  •  | 
  •  

Pregunta

Esto no es legal:

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


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

Para hacer esto, debe reflexionar un poco sobre el tipo de objeto para T o debe usar Activator.CreateInstance.Ambos son bastante desagradables.¿Existe una mejor manera?

¿Fue útil?

Solución

No puede obligar a T a tener una firma de constructor particular que no sea un constructor vacío, pero puede obligar a T a tener un método de fábrica con la firma deseada:

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;
}

Sin embargo, sugeriría quizás usar un patrón de creación diferente, como Abstract Factory, para este escenario.

Otros consejos

No.Si no estuviera pasando parámetros, entonces podría restringir su tipo de parámetro para que requiera un constructor sin parámetros.Pero si necesita aprobar argumentos, no tendrá suerte.

where T : MyBaseClass, new()

solo funciona con constructor público sin parámetros.más allá de eso, volvamos a activador.CreateInstance (que realmente no es TAN malo).

Puedo ver que eso no funciona.

¿Pero qué te impide hacer esto?

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

Dado que todo se heredará de MyBaseClass, todos serán MyBaseClass, ¿verdad?

Lo probé y esto 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!");
        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top