Интересно о C#: Операторы приведения не подчиняются дистрибутивному закону
Эрик Липперт отвечает на вопрос, заданный на StackOverflow, по поводу оператора "?" и приведения типов.
Рассмотрим следующую ситуацию:
object result; bool isDecimal = GetAmount(out result); decimal amount = (decimal)(isDecimal ? result : 0);
Разработчик был глубоко удивлен, когда увидел, что данный код компилируется, но потом выдает ошибку приведения (invalid cast exception).
Кто-нибудь видит в чем причина?
В алгебре операция умножения более приоритетная чем операция сложения. Т.е. q * (r + s) - то же самое, что и q*r + q*s. Разработчик ожидал, что операция приведения более приоритетная, чем оператор условия. Это не то же самое, что
decimal amount = isDecimal ? (decimal)result : (decimal)0;
или даже лучше:
decimal amount = isDecimal ? (decimal)result : 0.0m;
Причина в том, что типы условного выражения должны быть согласованными для обеих частей. Правила языка не позволяют возвращать object в одной ветке и int в другой.
В нашем примере мы имеем типы object и int. В то время когда int может быть приведен к типу object, обратное утверждение не верно. Поэтому компилятор выбрал object, что эквивалентно коду:
decimal amount = (decimal)(isDecimal ? result : (object)0);
В нашем случае ноль возвращается как boxed int. Дальше boxed int приводится к decimal, а так как такое приведение не разрешено, мы получаем invalid cast exception.
Источник: Эрик Липперт