В C # 4.0 возможно ли получить класс из параметра универсального типа? - PullRequest
23 голосов
/ 05 мая 2011

Я пытался это, но я не могу понять это. Я хочу сделать это ...

public abstract class SingletonType<TSingleton, TBaseClass> : TBaseClass
    where TSingleton : TBaseClass, new()
    where TBaseClass : class
{
    static TSingleton _singleton;
    public static TSingleton Singleton
        => _singleton ?? (_singleton = new TSingleton());
}

План состоял в том, чтобы использовать его таким образом, чтобы он как бы «оборачивал» шаблон синглтона вокруг базового класса ...

public class SingletonFoo : SingletonType<SingletonFoo, Foo> {
}

Тем не менее, я продолжаю получать это

Невозможно получить из TBaseClass, так как это параметр типа

Хм ... Я думал, что типы - это именно то, из чего вы делаете !

Так чего мне не хватает?

Примечание: Это, конечно, тривиальный пример, поскольку он не добавляет ничего полезного, но предположим, что SingletonType имеет много другой логики, не связанной с вопросом, поэтому он был опущен сосредоточиться на вопросе под рукой.

Ответы [ 4 ]

26 голосов
/ 05 мая 2011

Общие типы в C # не являются шаблонами C ++;помните, универсальный тип должен работать для всех возможных аргументов типа.Шаблон должен работать только для конструкций, которые вы на самом деле делаете.

Этот вопрос является дубликатом;см. мой ответ на

Почему дженерики C # не могут быть получены из одного из параметров универсального типа, как в шаблонах C ++?

, чтобы больше размышлять над этим.По сути, короткий ответ заключается в том, что значительные затраты не перевешивают небольшие преимущества этой функции.Если вам не нравится этот ответ, см. Мой второй ответ:

Почему генерики C # не могут быть получены из одного из параметров универсального типа, как они могут в шаблонах C ++?

И если вам также не нравится этот ответ, см. Следующий вопрос:

Каковы веские причины желать того, чтобы дженерики .NET могли наследовать один из типов универсальных параметров?

18 голосов
/ 05 мая 2011

Нет, это невозможно. Например, возьмите тип, который объявлен sealed. Вы не можете наследовать от этого класса, и нет никаких ограничений, чтобы ограничивать незапечатанные типы, поэтому попытка наследовать от него через универсальный параметр невозможна.

1 голос
/ 05 мая 2011

Каждый тип имеет ровно 1 реальный, отдельный родительский класс, даже если используются дженерики.Даже при работе с открытым универсальным типом (например, typeof(List<>)) вы все равно можете найти родительский класс.

Если бы то, что вы хотели, было разрешено, это не было бы правдой, typeof(SingletonType<,> не будет иметьродительский тип, и это не разрешено.

0 голосов
/ 14 июня 2019

Нет, это невозможно, потому что, скажем, у вас есть этот класс:

class bar {
  int example = 0;
}

Теперь вот наш класс параметров типа:

class foo<T> : T {
  int example = 5;
}

Если бы мы создали переменную типа foo<bar>, то example смешалось бы.

...