Given...
int a = 1, b = 4;
Then...
a += b += a += b;
Is evaluated in C++...
(a += (b += (a += b))); // a = 14[5 + 9] (b = 9[4 + 5] (a = 5[1 + 4]))
... and in C#...
(a += (b += (a += b))); // a = 10[1 + 9] (b = 9[4 + 5] (a = 5[1 + 4]))
// ^ re-use of original value of a (1)
// instead of expected intermediate right-to-left
// evaluation result (5)
The above has been tested in both Visual Studio 2008 and 2012, so there is no suspicion of a recently introduced language bug.
However, I did expect C#'s behaviour to mimic C++'s and assume I need education. I understand the HOW of the expression evaluation logic and don't need MSIL explained. Having searched fairly extensively and failed to find relevant fine print in the language specification, I was hoping a language expert would explain WHY this is so.
And for the curious who want to know why on earth would I want to do this... There's a handly little C++ trick for a pretty efficient and tidy inline swap of two integral types which goes like this...
a ^= b ^= a ^= b;
I am disappointed to find it doesn't work in C# and curious as to why. This is about understanding C#'s low-level mechanics and rationale behind them. No more, no less and specifically no readability religion please.
NB
Please folks, this NOT a serious effort at squeezing everything onto one line!!!
For C (and later C++) operator precedence and associativity have always been precisely defined.
The standard right-to-left associativity for assignment operators makes the C/C++ version's behaviour 100% clear and predictable. It has worked for me on several compilers and platforms and I would consider a compiler that didn't behave like this to be faulty.
I acknowledge that the line of code is obfuscated, it is a curiosity and used as a "brain teaser" I might give a junior C/C++ programmer.
Clearly C# is different - and apparently deliberately so.
I seek an explantion of the design considerations that led to C#'s behavioural divergence from one of its ancestor languages. Even educated guessing would be welcomed.
Answered
Thanks to Alexander Stepaniuk.
Start with left-to-right evaluation of operands
a = 1 + theRest1 // (1)
theRest1 = b = 4 + theRest2 // (2)
theRest2 = a = 1 + 4 // (3)
(3) into (2): theRest1 = b = 4 + 5
(2) into (1): a = 1 + 9
A "WHY" explanation would still be appreciated.
But the C# specification is clear that the above is the correct evaluation.
And below is as close as we can get (I think) using 2 variables, to the C++ trick...
b ^= a ^= b;
a ^ = b;
I don't like it - for the record - because it breaks my intuition ;-)