Почему
byte someVar;
someVar -= 3;
действителен, но
byte someVar;
someVar = someVar - 3;
разве?
Почему
byte someVar;
someVar -= 3;
действителен, но
byte someVar;
someVar = someVar - 3;
разве?
Удивительно, но когда вы выполняете операции над байтами, вычисления будут выполняться с использованием значений int
, при этом байты неявно отображаются в (int)
. Это справедливо и для short
, а при выполнении арифметики с плавающей запятой аналогично float
преобразуется до double
.
Второй фрагмент эквивалентен:
byte someVar;
someVar = (int) someVar - 3;
Из-за этого вы должны вернуть результат обратно в (byte)
, чтобы заставить компилятор принять назначение.
someVar = (byte) (someVar - 3);
Здесь копия таблицы в спецификации CLI (Ecma 335), которая указывает, какие операнды действительны для двоичных числовых операторов типа A op B, где A и B являются операндами, а "op" - это оператор, как Opcodes.Sub, который вы используете в своем фрагменте:
Для этого требуются некоторые аннотации:
Обратите внимание на строку и столбец для F, оба операнда должны быть плавающей точкой, вы не можете напрямую добавить, скажем, int в double. Компилятор С# имеет дело с этим ограничением, автоматически преобразуя операнд int в double, чтобы оператор был действительным.
В зависимости от вашего вопроса: обратите внимание, что байтов, sbyte, char, short и ushort типов нет. В том же подходе компилятор преобразует операнды в наименьший тип, который может представлять значение, чтобы оператор мог использоваться. Который будет int32. Согласно таблице, результатом операции будет int32.
Теперь здесь rub: результат - int32, но для возврата к байтовому значению требуется сужение преобразования. От 32 бит до 8 бит. Эта проблема, потому что она теряет значительные бит. Компилятор С# требует, чтобы вы сделали это явным. Вы, по сути, признаете, что знаете, что делаете, и что знаете о потенциально удивительном результате. Как этот:
byte v = 255;
v = (byte)(v + 1);
Оператор - = является проблемой, потому что нет эффективного способа применить требуемый отбор. Это не выражается в синтаксисе языка. Использование (байт) 3 не имеет смысла, литерал преобразуется в int32 в любом случае, чтобы заставить оператора работать.
Они отразили проблему, компилятор автоматически издает приведение без вашей помощи.