Создайте универсальный экземпляр класса из статического метода в производном классе

У меня есть класс в C# с шаблоном и статическим методом, подобным

class BClass<T>
{
  public static BClass<T> Create()
  {
    return new BClass<T>();
  }
 }

От этого я получаю класс и указываю шаблонный параметр к базовому классу

class DClass : BClass<int> { }

Проблема происходит, когда я пытаюсь использовать статический метод создать экземпляр D

class Program
{
  static void Main(string[] args)
  {
    DClass d = DClass.Create();
  }
}

Дает ошибку компилятора, "Не может неявно преобразовать тип 'Тест. BClass <интервал>' для 'Тестирования. DClass'".

Добавление ниже броска приводит к исключению кастинга времени выполнения.

DClass d = (DClass)DClass.Create();

Там какой-либо succint путь состоит в том, чтобы позволить статическому методу создать экземпляры производного класса? Идеально я хотел бы эквивалент определения типа C++, и я не хочу ниже синтаксиса (который действительно работает).

BClass<int> d = DClass.Create();
7
задан Jack Nock 27 May 2010 в 11:45
поделиться

3 ответа

Да, это возможно, имея ссылку типа на сам тип. Обратите внимание, что в мире .NET мы говорим о дженериках, а не о шаблонах, которые имеют важные различия в работе.

class BClass<T, TSelf> where TSelf: BClass<T, TSelf>, new() {
    public static TSelf Create() {
        return new TSelf();
    }
}

class DClass: BClass<int, DClass> {}

class Program {
    static void Main(string[] args) {
        DClass d = DClass.Create();
    }
}
6
ответ дан 6 December 2019 в 15:19
поделиться

Кажется, что то, что вы хотите, чтобы DClass был псевдонимом для BClass . Но это не то, что у вас здесь. У вас есть то, что DClass происходит от BClass . Таким образом, вызов DClass.Create (); создает BClass , который не DClass (это наоборот ).

Это могло бы прояснить ситуацию. Предположим, у вас есть такая иерархия:

class Rectangle {
    static Rectangle Create() {
        return new Rectangle();
    }
}

class Square : Rectangle { }

// code elsewhere
var shape = Square.Create(); // you might want this to return a square,
                             // but it's just going to return a rectangle

Один из вариантов получить что-то похожее на функциональность, которая вам нужна, может заключаться в определении вашего метода Create следующим образом:

static TClass Create<TClass>() where TClass : BClass<T>, new() {
    return new TClass();
}

// code elsewhere
var shape = DClass.Create<DClass>();

Это немного беспорядочно (а также требует, чтобы вы напишите конструктор без параметров для DClass ). Если вы твердо настроены использовать метод Create для создания экземпляров ваших объектов, подумайте о написании для него фабричного класса.

7
ответ дан 6 December 2019 в 15:19
поделиться
class BClass<T>
    {
        public static T1 Create<T1, T2>() where T1 : BClass<T2>, new()
        {
            return new T1();
        }
    }

    class DClass : BClass<int> { }

    class Program
    {
        static void Main(string[] args)
        {
            DClass d = DClass.Create<DClass, int>();
        }
    }
1
ответ дан 6 December 2019 в 15:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: