Why is
byte someVar;
someVar -= 3;
valid but
byte someVar;
someVar = someVar - 3;
isnt?
Why is
byte someVar;
someVar -= 3;
valid but
byte someVar;
someVar = someVar - 3;
isnt?
Surprisingly, when you perform operations on bytes the computations will be done using int
values, with the bytes implicitly cast to (int)
first. This is true for short
s as well, and similarly float
s are up-converted to double
when doing floating-point arithmetic.
The second snippet is equivalent to:
byte someVar;
someVar = (int) someVar - 3;
Because of this you must cast the result back to (byte)
to get the compiler to accept the assignment.
someVar = (byte) (someVar - 3);
Here's a copy of a table in the CLI specification (Ecma 335) that specifies which operands are valid on the binary numeric operators of the type A op B, where A and B are the operands and "op" is the operator, like Opcodes.Sub that you are using in your snippet:
Some annotations are required with this:
Note the row and column for F, both operands must be floating point, you cannot directly add, say, an int to a double. The C# compiler deals with that limitation by automatically converting the int operand to double so that the operator is valid.
Relevant to your question: also note that the byte, sbyte, char, short and ushort types are not present. Same approach, the compiler converts the operands to the smallest type that can represent the value so that the operator can be used. Which will be int32. According to the table, the result of the operation will be int32.
Now here's the rub: the result is int32 but assigning that back to a byte value requires a narrowing conversion. From 32 bits to 8 bits. That's trouble because it loses significant bits. The C# compiler requires you to make that explicit. You essentially acknowledge that you know what you're doing and that you are aware of the potentially surprising result. Like this one:
byte v = 255;
v = (byte)(v + 1);
The -= operator is a problem because there is no effective way to apply that required cast. It isn't expressible in the language syntax. Using (byte)3 doesn't make sense, the literal gets converted to int32 anyway to make the operator work.
They punted the problem, the compiler automatically emits the cast without your help.