суббота, 17 октября 2009 г.

Отличие между оператором "as" и операцией приведения типа

Это перевод оригинальной статьи находящейся здесь. Все права на оригинал принадлежат автору.

Большинство разработчиков скажут вам, что разница между «(Alpha) bravo» и «bravo as Alpha» состоит в том, что при ошибке приведения типа в первом случае будет выброшено исключение, тогда как во втором случае будет возвращен null. Хотя это действительно так, и это наиболее очевидное отличие, оно не единственно. Есть несколько подводных камней, которых нужно остерегаться.
В-первых, поскольку результатом оператора «as» может быть «null», тип результата должен быть таким, чтобы он в принципе мог принимать значение «null», то есть быть либо ссылочным типом, либо «nullable». Невозможно выполнить «as int» – это бессмысленно. Если аргумент окажется переменной не приводимой к типу «int», то каким же тогда должно быть возвращаемое значение? Так как результат операции «as» может принимать значение «null», то переменная, которой он присваивается, должна быть именованного типа.
Во-вторых, оператор приведения типа cast, это довольно странный зверь. Это связано с двумя противоречащими друг другу действиями: «проверь, действительно ли этот объект заданного типа и выбрось исключение, если нет» и «этот объект не того типа, что указан – найди мне эквивалентное значение указанного типа». Последнее означает, что оператор «cast» не выполняется оператором «as». Если вы напишете:
short s = (short)123;
int? i = s as int?.
вам не светит удача. Оператор «as» не выполнит преобразование, изменяющее представление, из «short» в «nullable int», как бы это сделал оператор приведения типа. Похожим образом, если у вас есть класс Alpha и не связанный с ним класс Bravo, с определённым пользователем преобразованием из Bravo в Alpha, операция «(Alpha) bravo» вызовет заданное пользователем преобразование, а «bravo as Alpha» – нет. Оператор «as» подразумевает только преобразования ссылок – упаковку (boxing) и распаковку (unboxing).
И последнее. Несомненно, случаи применения эти двух операторов внешне похожи, но по смыслу (семантически) очень различаются. Оператор приведения типа сообщает читателю: «Я уверен, что это преобразование корректно, и готов обработать исключение, если это не так». Оператор «as» говорит иное: «Я не знаю, корректно ли это преобразование или нет – давайте попробуем и посмотрим, что из этого выйдет».