We know that these two addition statements are equivalent and compile to the same IL code:
int x = 100;
x += 100;
x = x + 100;
However, when there is an explicit cast required I have noticed something strange:
byte b = 100;
b += 200; // Compiles (1)
b = b + 200; // Cannot implicitly convert int to byte (2)
b = (byte) (b + 200); // Compiles (3)
It is obvious why the second statement requires an explicit cast because the result of the addition is an integer. But the weird thing to me is the first statement. It compiles to the exact same IL as the third statement, so it looks like compiler adds a cast that is supposed to be explicit, for us. But it can't do it in the second statement.
It seems contradictory to me because I would expect the first statement to be equivalent to the second and never compile, so why does it compile?
Note: This doesn't compile when an explicit cast is required from long
to int
:
int x = 100;
long y = 200;
x += y;
You really need to go to the specs for this sort of information (and it can be really hard to get your head around the wording). However, straight from the horses mouth
12.18.3 Compound assignment
An operation of the form
x op= y
is processed by applying binary operator overload resolution (§12.4.5) as if the operation was writtenx op y.
Then,
If the return type of the selected operator is implicitly convertible to the type of
x
, the operation is evaluated asx = x op y
, except that x is evaluated only once.Otherwise, if the selected operator is a predefined operator, if the return type of the selected operator is explicitly convertible to the type of
x
, and ify
is implicitly convertible to the type ofx
or the operator is a shift operator, then the operation is evaluated asx = (T)(x op y)
, whereT
is the type ofx
, except thatx
is evaluated only once.- Otherwise, the compound assignment is invalid, and a binding-time error occurs.
...
blah blah blah
...
The second rule above permits
x op= y
to be evaluated asx = (T)(x op y)
in certain contexts. The rule exists such that the predefined operators can be used as compound operators when the left operand is of typesbyte
,byte
,short
,ushort
, orchar
. Even when both arguments are of one of those types, the predefined operators produce a result of type int, as described in §12.4.7.3. Thus, without a cast it would not be possible to assign the result to the left operand.The intuitive effect of the rule for predefined operators is simply that
x op= y
is permitted if both ofx op y
andx = y
are permitted.byte b = 0; char ch = '\0'; int i = 0; b += 1; // Ok b += 1000; // Error, b = 1000 not permitted b += i; // Error, b = i not permitted b += (byte)i; // Ok ch += 1; // Error, ch = 1 not permitted ch += (char)1; // Ok
the intuitive reason for each error is that a corresponding simple assignment would also have been an error.
In short, computer says no.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With