Есть ли элегантный способ создания экземпляра типа переменной с параметрами? - PullRequest
0 голосов
/ 19 сентября 2008

Это не законно:

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


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

Чтобы сделать это, вы должны отразить объект типа для T или использовать Activator.CreateInstance. Оба довольно противные. Есть ли лучший способ?

Ответы [ 4 ]

2 голосов
/ 19 сентября 2008

Неа. Если вы не передаете параметры, вы можете ограничить свой тип param требованием конструктора без параметров. Но если вам нужно передать аргументы, вам не повезло.

1 голос
/ 19 сентября 2008

Вы не можете ограничить T иметь конкретную сигнатуру конструктора, отличную от пустого конструктора, но вы можете ограничить T, чтобы иметь фабричный метод с желаемой сигнатурой:

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

Однако я бы предложил использовать для этого сценария другой шаблон творчества, такой как Абстрактная фабрика.

0 голосов
/ 19 сентября 2008

Я вижу, что не работает.

Но что вам мешает это сделать?

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

Поскольку все будет наследоваться от MyBaseClass, они всегда будут MyBaseClass, верно?

Я попробовал, и это работает.

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!");
        }
    }
}
0 голосов
/ 19 сентября 2008
where T : MyBaseClass, new()

работает только с публичным конструктором без параметров. кроме того, вернемся к activator.CreateInstance (что на самом деле неплохо).

...