Есть ли разница между назначением литых и сильных типов?
Я как-то наткнулся на это сегодня, когда писал код. В качестве примера возьмем следующее:
long valueCast = (long)(10 + intVariable);
long valueTyped = 10L + intVariable;
Есть ли разница между этими двумя или они скомпилированы точно так же? Есть ли соглашение для одного над другим?
Итак, я знаю, что это не критический вопрос (оба работают). Мне просто очень интересно узнать, какие отличия могут быть!
EDIT. Изменен пример кода, который будет ближе к моему первоначальному сценарию. Я хотел, чтобы вопрос был ясен, поэтому я заменил переменную константой. Не понял, что компилятор автоматически выполнил арифметику (тем самым изменив ответы на этот вопрос)
Ответы
Ответ 1
Да, между этими двумя есть большая разница. Не для тех конкретных значений, но то же самое выражение с разными значениями покажет разницу.
В первой версии добавление выполняется в 32-разрядной арифметике, а затем результат преобразуется в long
.
Во второй версии первый операнд уже есть long
, поэтому второй операнд продвигается до long
, и добавление затем выполняется в 64-разрядной арифметике.
Конечно, в этом случае компилятор все равно будет выполнять арифметику (и в обоих случаях прийти к одному и тому же выводу), но важно понять разницу между преобразованием результата операции и преобразованием одного из операндов операция.
В качестве примера:
unchecked
{
long valueCast = (long)(2000000000 + 2000000000);
long valueTyped = 2000000000L + 2000000000;
Console.WriteLine(valueCast);
Console.WriteLine(valueTyped);
}
Результат:
-294967296
4000000000
Обратите внимание, что это нужно делать в явно неконтролируемом контексте, поскольку в противном случае первое добавление даже не будет компилироваться - вы получите сообщение об ошибке "CS0220: операция переполняется во время компиляции в режиме проверки".
Ответ 2
Ну, это ошибка компиляции:
long valueCast = (long)(2147483647 + 2);
"Операция переполняется во время компиляции в режиме проверки."
В то время как это прекрасно работает:
long valueTyped = (2147483647L + 2);
Как говорит Джон Скит, разница заключается в том, конвертируете ли вы в long
перед выполнением суммы или после нее.
Ответ 3
В вашем примере 10L + 2; равен ((длинный) 10) + 2;
Это не то же самое (длинное) (10 + 2), потому что:
Операция (long) (10 + 2) выполняется как int (32 бит), а затем преобразуется в длинный (64-битный)
((длинный) 10) + 2; операция выполняется так долго (64 бит), потому что 10 преобразуется в задолго до фактической операции