'static' value appears to reset after function call
Just look at the generated CIL:
.method private hidebysig static int32 foo() cil managed
{
// Code size 19 (0x13)
.maxstack 2
.locals init ([0] int32 V_0)
IL_0000: nop
IL_0001: ldsfld int32 Program::'value'
IL_0006: ldc.i4.7
IL_0007: sub
IL_0008: stsfld int32 Program::'value'
IL_000d: ldc.i4.1
IL_000e: stloc.0
IL_000f: br.s IL_0011
IL_0011: ldloc.0
IL_0012: ret
} // end of method Program::foo
IL_0001:
- Push the value of the static field on the stack. s:[value(0)]IL_0006:
- Push7
onto the stack. s:[7, value(0)]IL_0007:
- Subtracts value2 (7
) from value1 (0
), returning a new value (-7).IL_0008:
- Replaces the value of the static field with val (value = -7).IL_000d:
- Push1
onto the stack. s:[1, 7, value(-7)]IL_000e:
- Pop a value from stack into local variable 0. (lv = 1)IL_0011:
- Load local variable 0 onto stack. s:[lv(1), 7, value(-7)]IL_0012:
- Return (lv(1))
And the Main
method:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 29 (0x1d)
.maxstack 8
IL_0000: nop
IL_0001: ldsfld int32 Program::'value'
IL_0006: call int32 Program::foo()
IL_000b: sub
IL_000c: stsfld int32 Program::'value'
IL_0011: ldsfld int32 Program::'value'
IL_0016: call void [mscorlib]System.Console::WriteLine(int32)
IL_001b: nop
IL_001c: ret
} // end of method Program::Main
IL_0001:
- pushesvalue
onto stack (which is0
)IL_0006:
- callsfoo
(which will return1
)IL_000b:
- subtract values:value2(1)
fromvalue1(0)
(value(0) - value(1) = -1
).
So the result is -1
.
This problem is not about static; it's about how the subtraction works.
value -= foo();
can be expanded to value = value - foo()
The compiler will explain it into four steps:
- Load the value of
value
onto the stack. - Call the method
foo
and put the result onto the stack. - Do subtraction with these two values on the stack.
- Set the result back to
value
field.
So the original value of value
field is already loaded. Whatever you change value
in the method foo
, the result of the subtraction won't be affected.
If you change the order to value = - foo() + value
, then the value of value
field will be loaded after foo
is called. The result is -8
; that's what you are expected to get.
Thanks for Eliahu's comment.
The statement
value -= foo(); // short for value = value - foo();
is equivalent to
var temp = value; // 0
var fooResult = foo(); // 1
value = temp - fooResult; // -1
That's why you are getting -1