x+=x++;
Luca Bolognese -Today I was looking through an internal C# user group list. One of the messages was about x+=x++; and what should be the right behavior. I thought this is more generally interesting, so I decided to blog it. But first, DO NOT WRITE THAT CODE!!!
Ok, with that out of the way, we can start…
Let’s take this code as an example:
int x = 3;
x += x++;
The first thing the compiler does whenever it sees something like z += y is to convert it to z = z + y. This is obviously true for +=, -=, *=, and /=. Ok, this was easy. Now we have just to consider:
x= x + x++;
This, by the way, gives the same result as:
x = x + x;
This, by the way, gives a different result from:
x = x++ + x;
This, by the way gives the same result as:
x = x + ++x;
As maddening as this may seem, it actually makes sense (once you understand how it works). But first, what is the difference between x++ and ++x? x++ returns the value of x to the current expression and then increments x. ++x increments x and then return its value to the current expression. Given this factoid (and knowing that c# evaluates expressions left to right), we can then consider what happens in the following case:
int x = 3;
x = x + x++;
Here is how the compiler conceptually evaluates it:
- x = (x) + x++ -> the first x gets evaluated and returns 3, x = 3
- x = 3 + (x)++ -> x gets evaluated and returns 3, x = 3
- x = 3 + (x++) -> x++ gets evaluated and x is incremented (to 4), x = 4
- x = (3 + 3) -> 3 + 3 gets evaluated and returns 6, x = 4
- (x = 6) -> x is assigned to 6 (overriding the previous value of 4)
Now let’s see how this one works:
int x = 3;
x = x++ + x;
- x = (x)++ + x -> x gets evaluated and returns 3, x =3
- x = (x++) + x -> x++ gets evaluated and x is incremented, x=4
- x = 3 + (x) -> x gets evaluated and returns 4, x = 4
- x = 3 + 4 -> 3+4 gets evaluated and returns 7, x = 4
- (x=7) -> x is assigned to 7 (overriding the previous value of 4)
Now let’s get to this one:
int x = 3;
x = x + ++x;
- x = (x) + ++x -> x gets evaluated and returns 3, x=3
- x = 3 + (++x) -> ++x gets evaluated and x is incremented, x=4
- x = 3 + (x) -> x gets evaluated and returns 4, x=4
- x = 3 + 4 -> 3+4 gets evaluated and returns 7, x = 4
- (x=7) -> x is assigned to 7 (overriding the previous value of 4)
I hope this is clear. By the way, in c++ the behavior for this expression is undefined…
But now… why did we make this legal? Why not err or warn at compilation time? Well…
- We were wrong, we should have erred or warned, but now it is too late because if we change this we break code OR
- It is quite complex to form a set of guidelines that the compiler can evaluate to be able to err just in the bizarre cases OR
- We prefer to spend our time working on things people really care about instead of these corner-corner-corner cases
Does it matter which of the previous options is the correct one? Not really because…
YOU ARE NOT GOING TO WRITE THAT CODE J
Tags
- CSHARP