C# Twitter quiz explained
Yesterday I twittered out a quiz:
C# pop quiz. Without testing, what is the value of x here: ‘var x = 10; x += x--;’?
A lot of people guessed 19 while a few guessed the correct answer of 20. Looking at the IL posted by TehGrumpyDude, we can see what happens on the stack level when this executes:
ldc.i4.s 10 ; [10] stloc.0 ; [] ldloc.0 ; [10] ldloc.0 ; [10, 10] dup ; [10, 10, 10] ldc.i4.1 ; [10, 10, 10, 1] sub ; [10, 10, 9] stloc.0 ; [10, 10] add ; [20] stloc.0 ; []
However, some argued that this simply shows why the Microsoft implementation of C# performs this way, and that possibly the C# spec itself doesn’t define a concrete behavior. I shot some mail to Eric Lippert who enlightened me beyond what I was even hoping to get out of the conversation. It all boiled down to this bit:
If you read the specification sections on assignment operators and increment operators, it is clearly spelled out. The rules for all expression evaluations are:
* subexpressions of every expression are evaluated in strictly left-to-right order
* operators are executed in the order determined by precedence and associativity.So, for example, if you have F() + G() * H(), then the subexpressions F(), G() and H() are executed in that order. Their results are then combined by multiplying the result of G() by the result of H(), and then adding the result of F(). See what happened there? subexpressions left to right, operators in precedence order.
The rules for A += B are clearly stated in the specification. Briefly:
1) evaluate A as a variable (or property, and so on), and obtain its value
2) evaluate B as a value
3) add the value of step 1 to B using the addition operator identified by overload resolution.
4) cast the result of step 3 back to the type of A if necessary
5) assign the result of step 4 to the variable/property/whatever identified in step 1.The rules for X-- are also clearly stated in the specification. Briefly:
1) Evaluate X as a variable (or property or whatever)
2) Fetch the value of the variable identified in step 1
3) Subtract one from that value
4) Store the result of step 3 in the variable identified in step 1
5) the result of the expression is the result of step 2.So, put it all together. Subexpressions are evaluated left to right, and then operations are performed in precedence order, so with x += x--, it goes:
1) evaluate x as a variable. Its value is 10.
2) evaluate x-- :
2a) evaluate x as a variable
2b) fetch the value of the variable identified in step 2a, which is 10.
2c) subtract one from that value: 9
2d) store the result of step 2c in the result of step 2b, so x becomes 9.
2e) result of the expression is the result of step 2b, which was 10.
3) add the value of step 1 to the value of step 2, so 10 + 10 = 20
4) casting is unnecessary
5) Store the result of step 4 in the variable identified in step 1. So x becomes 20.
So there you go.
This was very confusing for me, possibly because I’m not the big programmer most readers are. However, I found that this explanation helped me to understand the ‘–’ issue.
“The decrement operator (–) decrements its operand by 1. The decrement operator can appear before or after its operand: –variable and variable–. The first form is a prefix decrement operation. The result of the operation is the value of the operand “after” it has been decremented. The second form is a postfix decrement operation. The result of the operation is the value of the operand “before” it has been decremented.”
Quote from MSDN (http://msdn.microsoft.com/en-us/library/wc3z3k8c.aspx)