Я знаю, что уже есть несколько сообщений, касающихся разницы между приведением типов и оператором 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
, а преобразование - нет?