I may as well start with my pet peeve… The C# compilers failure to generate correct code for the following expression:
a ^= b ^= a ^= b;
Before C#, I (and many others, I’m sure) used that in C. For those who are not familiar with that expression, it basically swaps the variables a and b. They’re usually a numeric type.
So, way back in 2003 (using Visual Studio 2003), some friends and I were testing out swap functions to see which one was the fastest, and I tried this XOR swap. I took notice when I started getting bizarre results. You can try it out for yourselves.
Now, let’s take a look at the generated code (x86) for that expression:
mov eax,dword ptr [ebp-44h] mov dword ptr [ebp-4Ch],eax mov eax,dword ptr [ebp-48h] xor dword ptr [ebp-44h],eax mov eax,dword ptr [ebp-44h] xor dword ptr [ebp-48h],eax mov eax,dword ptr [ebp-4Ch] xor eax,dword ptr [ebp-48h] mov dword ptr [ebp-44h],eax
And if you translate that back into C# (or C for that matter), it is:
temp = a; a ^= b; b ^= a; temp ^= b; a = temp;
As you can see, the compiler makes use of a temp variable, and it basically makes a mistake with it. In the assembly above, it makes the mistake at line 7. It used the initial value of a which it saved in the beginning instead of the new value by the earlier XOR operations. By the time it gets to that last XOR, b already has the value of a, and therefore results in a zero instead of a correct swap.
Others have encountered this, and there has been some debate about how C# evaluates such expressions. Regardless, such expressions have to be evaluated from right-to-left. However, it seems the compiler uses the ‘old’ values for the left operand, and just by luck, it got the first b (from the left) XOR right as it wasn’t modified in the first XOR operation (right most). So how did the Microsoft C compiler get it right? Because it uses the latest values for a and b each time one of the XOR’s is processed. This is the correct way to do it, and you would then get the results you expect.
Therefore, if this is a ‘feature’, it’s hard to say it is a good one by any stretch of the imagination. It must be a bug. And not only that, it is still there in Visual Studio 2010. I can understand that this is a low priority issue if it is indeed a bug as it can be easily worked around by breaking up the expression into the more obvious:
a ^= b; b ^= a; a ^= b;
Don’t you just love it when it ain’t your fault?