This is actually undefined behaviour in C and C++. For example, C states that reading and modifying an object without an intervening sequence point is undefined.
However, C# locks down the behaviour so that behaviour is defined. From the online docs:
Unrelated to operator precedence and associativity, operands in an expression are evaluated from left to right. The following examples demonstrate the order in which operators and operands are evaluated:
OPERAND EVALUATION
Expression Order of evaluation
a + b a, b, +
a + b * c a, b, c, *, +
a / b + c * d a, b, /, c, d, *, +
a / (b + c) * d a, b, c, +, /, d, *
And, from the operator precedence table, you can see that ++x
(unary category) has a higher precedence than x + y
(additive category).
In your case, the sub-expression ++x
is evaluated first and results in x
being pre-incremented so the value of that sub-expression is the original x
plus one.
Then the sub-expression --x
is evaluated and results in x
(already incremented from the previous step) being pre-decremented so the value of that sub-expression is the original x
.
And, since x + 1 - x == 1
for all but the darkest corners of the math universe, the result is always one. I still wouldn't do something like this, but it at least is well defined.