Повторное обращение к оператору преобразования «как»

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

  • Оператор as не выбрасывает, а возвращает null , если преобразование завершилось неудачно
  • Следовательно, оператор as работает только со ссылочными типами
  • Оператор as не будет использовать определяемые пользователем операторы преобразования

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

Но здесь работает кое-что еще. Подумайте:

static void MyGenericMethod<T>(T foo)
{
    var myBar1 = foo as Bar;  // compiles
    var myBar2 = (Bar)foo;    // does not compile ('Cannot cast expression of
                              // type 'T' to type 'Bar')
}

Пожалуйста, не обращайте внимания на то, является ли этот явно сокрушительный пример хорошей практикой или нет. Меня беспокоит очень интересное различие между ними в том, что приведение не будет компилироваться, тогда как как делает. Я действительно хотел бы знать, может ли кто-нибудь пролить свет на это.

Как часто отмечается, оператор as не учитывает пользовательские преобразования, но в приведенном выше примере он явно более эффективен из двух. Обратите внимание, что , как и , что касается компилятора, нет известной связи между (неизвестным во время компиляции) типом T и Bar. Актерский состав полностью исполняется. Должны ли мы подозревать, что приведение полностью или частично разрешено во время компиляции, а оператор as - нет?

Между прочим, добавление ограничения типа неудивительно фиксирует приведение, таким образом:

static void MyGenericMethod<T>(T foo) where T : Bar
{
    var myBar1 = foo as Bar;  // compiles
    var myBar2 = (Bar)foo;    // now also compiles
}

Почему компилируется ли оператор as , а преобразование - нет?

21
задан DavidRR 19 May 2014 в 00:04
поделиться