Есть ли элегантный способ создать экземпляр типа переменной с параметрами?

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

  •  01-07-2019
  •  | 
  •  

Вопрос

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

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


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

Чтобы сделать это, вы должны немного поразмышлять над типом object для T или вы должны использовать Activator.CreateInstance.И то, и другое довольно противно.Есть ли способ получше?

Это было полезно?

Решение

Вы не можете ограничить 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;
}

Тем не менее, я бы предложил, возможно, использовать другой шаблон создания, такой как Abstract Factory для этого сценария.

Другие советы

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

where T : MyBaseClass, new()

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

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

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

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!");
        }
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top