Let’s take a look at the intermediary language code for that:
IL_0001: ldc.i4.s 2A
IL_0003: stloc.0 // c
IL_0004: ldloc.0 // c
This loads the constant integer
42 onto the stack, then stores it into the variable
c, and loads it immediately again onto the stack.
This copies the value into another register, and also loads it again.
This adds the constant 1 to the loaded value
IL_0009: stloc.0 // c
… and stores the result (43) into the variable
IL_000B: stloc.0 // c
Then the value from the other register is loaded (that’s still 42!) and stored into the variable
IL_000C: ldloc.0 // c
IL_000D: call System.Console.WriteLine
Then the value (42) is loaded from the variable, and printed.
So what you can see from this is that while
c++ increments the variable by one after the result was returned, that incrementing happens still before assinging the value to the variable. So the sequence is more like this:
- Get value from
- Assign previously read value to
And that should explain why you get that result :)
To add one more example, since this was mentioned in a comment that was since deleted:
c = c++ + c;
This works very similarly: Assuming an initial value of 2 again, the left side of the addition is evaluated first. So the value is read from the variable (2), then
c is incremented (
c becomes 3). Then the right side of the addition is evaluated. The value of
c is read (now 3). Then the addition takes place (2 + 3) and the result (5) is assigned to the variable.
The takeaway from this is that you should avoid mixing increment and decrement operations in normal expressions. While the behavior is very well defined and makes absolute sense (as shown above), it is still sometimes difficult to wrap your head around it. Especially when you assign something to the same variable that you increment in the expression, this becomes confusing quickly. So do yourself and others a favor and avoid increment/decrement operations when they are not completely on their own :)