Избыточное общее ограничение?

Рассмотрим следующий универсальный метод:

public T2 Frob<T1, T2>(T1 item)
        where T1 : class, T2
        => item as T2;

Компилятор откажется компилировать этот код; Параметр типа 'T2' нельзя использовать с оператором 'as', потому что он не имеет ограничения типа класса или ограничения 'class'

Хорошо, это легко решить, просто выполнив:

public T2 Frob<T1, T2>(T1 item)
        where T1 : class, T2
        where T2 : class
        => item as T2;

Но разве это не лишнее? Есть ли возможный T2, который не является class, учитывая ограничения, уже существующие для T1?

У меня вопрос не в том, почему этот «вывод» не был реализован в компиляторе, причиной может быть просто «никто об этом не подумал», и это нормально. Мне больше интересно знать, верны ли мои рассуждения в том, что T2 эффективно и во всех случаях ограничивается значением class в первом примере, даже если это явно не применяется.


person InBetween    schedule 13.02.2017    source источник
comment
Как вы думаете, почему ограничения для T1 применяются также и для T2? У них нет ничего общего, в частности, хотя T1 происходит от T2, T2 не знает ничего о T1.   -  person HimBromBeere    schedule 13.02.2017
comment
Конечно, но сам T2 ничем не ограничен, это может быть даже struct.   -  person HimBromBeere    schedule 13.02.2017
comment
@HimBromBeere дает мне один пример ссылочного класса, производного от типа значения, потому что это именно то, что должно произойти с ограничениями, установленными для T1.   -  person InBetween    schedule 13.02.2017
comment
@HimBromBeere Я думаю, что OP означает, что T2 не может быть типом значения, потому что T1 не может быть производным от типа значения. Так что это обязательно должен быть ссылочный тип.   -  person René Vogt    schedule 13.02.2017
comment
А, ладно, понятно. Тогда я думаю, что ваши рассуждения верны, однако они не реализованы из-за уже упомянутого факта.   -  person HimBromBeere    schedule 13.02.2017
comment
@ RenéVogt, откуда он берется?   -  person MistyK    schedule 13.02.2017
comment
Лично я считаю, что эти вопросы в основном основаны на мнениях, но на вопросы о том, почему разработчики C # реализовали X в компиляторе, уже были даны ответы, так что ... что я знаю.   -  person Jamiec    schedule 13.02.2017
comment
Мои два цента здесь заключаются в том, что это просто вариант использования, который в настоящее время не реализован в дженериках.   -  person Matías Fidemraizer    schedule 13.02.2017
comment
Я имею в виду, что T1 является классом и является производным T2, поэтому T2 также является ссылочным типом   -  person Matías Fidemraizer    schedule 13.02.2017
comment
@Jamiec Если вы читаете мой вопрос, я не спрашиваю почему компилятору требуется избыточное ограничение. Я спрашиваю, является ли он избыточным или есть какой-то очень странный угловой случай, когда это не так. Ничего не могу придумать, но хочу быть уверенным на 100%.   -  person InBetween    schedule 13.02.2017
comment
Хотя этот вопрос хорош и показывает возможности исследования, я не вижу никакого ответа на него, кроме как просто сказать: да, ваши рассуждения верны, однако поведение, которое вы хотите, предполагает обратное ограничение, которое не реализовано.   -  person HimBromBeere    schedule 13.02.2017
comment
Так или иначе, вы спрашиваете, почему человек реализовал это таким образом, или же этот человек допустил ошибку. Это вопрос мотивации, и единственный человек, который может ответить на него, - это человек, который его реализовал.   -  person Jamiec    schedule 13.02.2017
comment
@HimBromBeere: Ну, это хороший ответ на хороший вопрос, не так ли?   -  person O. R. Mapper    schedule 13.02.2017


Ответы (1)


Моя интерпретация этого, учитывая спецификации C # 5.0, говорят в 7.10.11, оператор as:

В операции формы E as T, E должно быть выражением, а T должно быть ссылочным типом, параметром типа, известным как ссылочный тип, или типом, допускающим значение NULL.

Компилятор в этот момент учитывает только T2 в этом блоке:

public T2 Frob<T1, T2>(T1 item)
        where T1 : class, T2
        => item as T2;

И он видит, что сам T2 не ограничен. Конечно, можно вычесть, что в этом случае ожидается, что T1 будет ссылочным типом и наследует T2, поэтому сам T2 также должен быть ссылочным типом, но я конечно, есть причины не делать этого.

person CodeCaster    schedule 13.02.2017
comment
На самом деле, вероятно, нет причин для этого, кроме тех, которые Эрик Липперт отмечает в этом ответе: stackoverflow.com/a / 1843557. TL; DR: Реализация функций требует времени. - person aquinas; 13.02.2017