x+=x++;

-

Today I was look­ing through an in­ter­nal C# user group list. One of the mes­sages was about x+=x++; and what should be the right be­hav­ior. I thought this is more gen­er­ally in­ter­est­ing, so I de­cided to blog it. But ﬁrst, DO NOT WRITE THAT CODE!!!

Ok, with that out of the way, we can start…

Let’s take this code as an ex­am­ple:

int x = 3;

x += x++;

The ﬁrst thing the com­piler does when­ever it sees some­thing like z += y is to con­vert it to z = z + y. This is ob­vi­ously true for +=, -=, *=, and /=. Ok, this was easy. Now we have just to con­sider:

x= x + x++;

This, by the way, gives the same re­sult as:

x = x + x;

This, by the way, gives a dif­fer­ent re­sult from:

x = x++ + x;

This, by the way gives the same re­sult as:

x = x + ++x;

As mad­den­ing as this may seem, it ac­tu­ally makes sense (once you un­der­stand how it works). But ﬁrst, what is the dif­fer­ence be­tween x++ and ++x? x++ re­turns the value of x to the cur­rent ex­pres­sion and then in­cre­ments x. ++x in­cre­ments x and then re­turn its value to the cur­rent ex­pres­sion. Given this fac­toid (and know­ing that c# eval­u­ates ex­pres­sions left to right), we can then con­sider what hap­pens in the fol­low­ing case:

int x = 3;

x = x + x++;

Here is how the com­piler con­cep­tu­ally eval­u­ates it:

1. x = (x) + x++ -> the first x gets evaluated and returns 3, x = 3
2. x = 3 + (x)++ -> x gets evaluated and returns 3, x = 3
3. x = 3 + (x++) -> x++ gets evaluated and x is incremented (to 4), x = 4
4. x = (3 + 3) -> 3 + 3 gets evaluated and returns 6, x = 4
5. (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;

1. x = (x)++ + x -> x gets evaluated and returns 3, x =3
2. x = (x++) + x -> x++ gets evaluated and x is incremented, x=4
3. x = 3 + (x) -> x gets evaluated and returns 4, x = 4
4. x = 3 + 4 -> 3+4 gets evaluated and returns 7, x = 4
5. (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;

1. x = (x) + ++x -> x gets evaluated and returns 3, x=3
2. x = 3 + (++x) -> ++x gets evaluated and x is incremented, x=4
3. x = 3 + (x) -> x gets evaluated and returns 4, x=4
4. x = 3 + 4 -> 3+4 gets evaluated and returns 7, x = 4
5. (x=7) -> x is assigned to 7 (overriding the previous value of 4)

I hope this is clear. By the way, in c++ the be­hav­ior for this ex­pres­sion is un­de­ﬁned…

But now… why did we make this le­gal? Why not err or warn at com­pi­la­tion 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 mat­ter which of the pre­vi­ous op­tions is the cor­rect one? Not re­ally be­cause…

YOU ARE NOT GOING TO WRITE THAT CODE J

• CSHARP