'static' value appears to reset after function call [duplicate]Behaviour and Order of evaluation in C#How exactly do static fields work internally?order of evaluation of operandsCan not round trip html format to clipboardList, not lose the reference Why is this Java code 6x faster than the identical C# code?WCF Guid DataMember not Serialized properlyHow to pass a sql connections string value to a C# programC# why object can't be converted to intStatic function returns unexpectedly when called from constructorExit a method back to Main?get set accessors from static Main() - and best practice for boolean storeWidth 100% and height 100% not working in chrome
Why are angular mometum and angular velocity not necessarily parallel, but linear momentum and linear velocity are always parallel?
Problem loading expl3 in plain TeX
401(k) investment after being fired. Do I own it?
Why did modems have speakers?
How do I run a game when my PCs have different approaches to combat?
Examples of solving for unknowns using equivalence relations that are not equality, inequality, or boolean truth?
"I you already know": is this proper English?
Why did NASA use U.S customary units?
Keeping an "hot eyeball planet" wet
Why are so many countries still in the Commonwealth?
Other than a swing wing, what types of variable geometry have flown?
How to handle aversion that derives from perceiving arrogance?
Why keep the bed heated after initial layer(s) with PLA (or PETG)?
Where is this photo of a group of hikers taken? Is it really in the Ural?
How can I stop myself from micromanaging other PCs' actions?
How may I shorten this shell script?
How to sort and filter a constantly changing list of data?
Spoken encryption
Why is the return type for ftell not fpos_t?
Where to place an artificial gland in the human body?
What is the meaning of "a thinly disguised price"?
Character Frequency in a String
Which creatures count as green creatures?
Why are off grid solar setups only 12, 24, 48 VDC?
'static' value appears to reset after function call [duplicate]
Behaviour and Order of evaluation in C#How exactly do static fields work internally?order of evaluation of operandsCan not round trip html format to clipboardList, not lose the reference Why is this Java code 6x faster than the identical C# code?WCF Guid DataMember not Serialized properlyHow to pass a sql connections string value to a C# programC# why object can't be converted to intStatic function returns unexpectedly when called from constructorExit a method back to Main?get set accessors from static Main() - and best practice for boolean storeWidth 100% and height 100% not working in chrome
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
This question already has an answer here:
Behaviour and Order of evaluation in C# [duplicate]
2 answers
I found a lot of articles about statics (MSDN, MSDN 2, Stack Overflow, and lot lot more), but I still can't understand why this code returns -1:
class Program
static int value = 0;
static int foo()
value = value - 7;
return 1;
static void Main(string[] args)
value -= foo();
Console.WriteLine(value);
Console.ReadKey();
Here's what the debugger shows after foo() has run, but before the result is subtracted from value:

But one step later, value is -1:

I would expect -8 because of the static field which is stored in memory once.
When I changed it to
var x = foo();
value -= x;
it shows -8
How does this work exactly?
c#
marked as duplicate by GSerg, dandan78, Silviu Burcea, TnTinMn, TheGeneral 17 mins ago
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
|
show 10 more comments
This question already has an answer here:
Behaviour and Order of evaluation in C# [duplicate]
2 answers
I found a lot of articles about statics (MSDN, MSDN 2, Stack Overflow, and lot lot more), but I still can't understand why this code returns -1:
class Program
static int value = 0;
static int foo()
value = value - 7;
return 1;
static void Main(string[] args)
value -= foo();
Console.WriteLine(value);
Console.ReadKey();
Here's what the debugger shows after foo() has run, but before the result is subtracted from value:

But one step later, value is -1:

I would expect -8 because of the static field which is stored in memory once.
When I changed it to
var x = foo();
value -= x;
it shows -8
How does this work exactly?
c#
marked as duplicate by GSerg, dandan78, Silviu Burcea, TnTinMn, TheGeneral 17 mins ago
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
8
@pappbence96 which is exactly what he expects, but isn't getting.
– TvanB
2 days ago
46
FYI, this has nothing to do with static.
– Ahmed Abdelhameed
2 days ago
7
Debuged this already , when method ends, value = -7, but step next it magically changed on "-1". Thas the problem which can't understand
– EmerG
2 days ago
13
value -= foo()is the same asvalue = current value of value (0) - foo() which returns 1, which is the same asvalue = 0 - 1.foo()does decrementvaluebut only after you've referenced it in the calculation that callsfoo(). Bad explanations have made it difficult to understand, but that's it in a nutshell.
– Archer
2 days ago
2
Statements likei += i++;are inherently ambiguous in meaning. Some languages have legalese in place that makes such statements well-defined, other languages (infamously the C family) just say: "The order of operand evaluation is undefined." It doesn't matter what category your language falls in, code that's ambiguous in this way should not be written as it's hard to understand.
– cmaster
yesterday
|
show 10 more comments
This question already has an answer here:
Behaviour and Order of evaluation in C# [duplicate]
2 answers
I found a lot of articles about statics (MSDN, MSDN 2, Stack Overflow, and lot lot more), but I still can't understand why this code returns -1:
class Program
static int value = 0;
static int foo()
value = value - 7;
return 1;
static void Main(string[] args)
value -= foo();
Console.WriteLine(value);
Console.ReadKey();
Here's what the debugger shows after foo() has run, but before the result is subtracted from value:

But one step later, value is -1:

I would expect -8 because of the static field which is stored in memory once.
When I changed it to
var x = foo();
value -= x;
it shows -8
How does this work exactly?
c#
This question already has an answer here:
Behaviour and Order of evaluation in C# [duplicate]
2 answers
I found a lot of articles about statics (MSDN, MSDN 2, Stack Overflow, and lot lot more), but I still can't understand why this code returns -1:
class Program
static int value = 0;
static int foo()
value = value - 7;
return 1;
static void Main(string[] args)
value -= foo();
Console.WriteLine(value);
Console.ReadKey();
Here's what the debugger shows after foo() has run, but before the result is subtracted from value:

But one step later, value is -1:

I would expect -8 because of the static field which is stored in memory once.
When I changed it to
var x = foo();
value -= x;
it shows -8
How does this work exactly?
This question already has an answer here:
Behaviour and Order of evaluation in C# [duplicate]
2 answers
c#
c#
edited 1 hour ago
J. Antonio Perez
5,94811 silver badges26 bronze badges
5,94811 silver badges26 bronze badges
asked 2 days ago
EmerGEmerG
3745 silver badges10 bronze badges
3745 silver badges10 bronze badges
marked as duplicate by GSerg, dandan78, Silviu Burcea, TnTinMn, TheGeneral 17 mins ago
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
marked as duplicate by GSerg, dandan78, Silviu Burcea, TnTinMn, TheGeneral 17 mins ago
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
8
@pappbence96 which is exactly what he expects, but isn't getting.
– TvanB
2 days ago
46
FYI, this has nothing to do with static.
– Ahmed Abdelhameed
2 days ago
7
Debuged this already , when method ends, value = -7, but step next it magically changed on "-1". Thas the problem which can't understand
– EmerG
2 days ago
13
value -= foo()is the same asvalue = current value of value (0) - foo() which returns 1, which is the same asvalue = 0 - 1.foo()does decrementvaluebut only after you've referenced it in the calculation that callsfoo(). Bad explanations have made it difficult to understand, but that's it in a nutshell.
– Archer
2 days ago
2
Statements likei += i++;are inherently ambiguous in meaning. Some languages have legalese in place that makes such statements well-defined, other languages (infamously the C family) just say: "The order of operand evaluation is undefined." It doesn't matter what category your language falls in, code that's ambiguous in this way should not be written as it's hard to understand.
– cmaster
yesterday
|
show 10 more comments
8
@pappbence96 which is exactly what he expects, but isn't getting.
– TvanB
2 days ago
46
FYI, this has nothing to do with static.
– Ahmed Abdelhameed
2 days ago
7
Debuged this already , when method ends, value = -7, but step next it magically changed on "-1". Thas the problem which can't understand
– EmerG
2 days ago
13
value -= foo()is the same asvalue = current value of value (0) - foo() which returns 1, which is the same asvalue = 0 - 1.foo()does decrementvaluebut only after you've referenced it in the calculation that callsfoo(). Bad explanations have made it difficult to understand, but that's it in a nutshell.
– Archer
2 days ago
2
Statements likei += i++;are inherently ambiguous in meaning. Some languages have legalese in place that makes such statements well-defined, other languages (infamously the C family) just say: "The order of operand evaluation is undefined." It doesn't matter what category your language falls in, code that's ambiguous in this way should not be written as it's hard to understand.
– cmaster
yesterday
8
8
@pappbence96 which is exactly what he expects, but isn't getting.
– TvanB
2 days ago
@pappbence96 which is exactly what he expects, but isn't getting.
– TvanB
2 days ago
46
46
FYI, this has nothing to do with static.
– Ahmed Abdelhameed
2 days ago
FYI, this has nothing to do with static.
– Ahmed Abdelhameed
2 days ago
7
7
Debuged this already , when method ends, value = -7, but step next it magically changed on "-1". Thas the problem which can't understand
– EmerG
2 days ago
Debuged this already , when method ends, value = -7, but step next it magically changed on "-1". Thas the problem which can't understand
– EmerG
2 days ago
13
13
value -= foo() is the same as value = current value of value (0) - foo() which returns 1, which is the same as value = 0 - 1. foo() does decrement value but only after you've referenced it in the calculation that calls foo(). Bad explanations have made it difficult to understand, but that's it in a nutshell.– Archer
2 days ago
value -= foo() is the same as value = current value of value (0) - foo() which returns 1, which is the same as value = 0 - 1. foo() does decrement value but only after you've referenced it in the calculation that calls foo(). Bad explanations have made it difficult to understand, but that's it in a nutshell.– Archer
2 days ago
2
2
Statements like
i += i++; are inherently ambiguous in meaning. Some languages have legalese in place that makes such statements well-defined, other languages (infamously the C family) just say: "The order of operand evaluation is undefined." It doesn't matter what category your language falls in, code that's ambiguous in this way should not be written as it's hard to understand.– cmaster
yesterday
Statements like
i += i++; are inherently ambiguous in meaning. Some languages have legalese in place that makes such statements well-defined, other languages (infamously the C family) just say: "The order of operand evaluation is undefined." It doesn't matter what category your language falls in, code that's ambiguous in this way should not be written as it's hard to understand.– cmaster
yesterday
|
show 10 more comments
6 Answers
6
active
oldest
votes
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
valueonto the stack. - Call the method
fooand put the result onto the stack. - Do subtraction with these two values on the stack.
- Set the result back to
valuefield.
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.
9
If you changevalue = foo() - valuetovalue = -foo() + value;in your last sentence you will get the 'expected' result-8
– Eliahu Aaron
2 days ago
4
@EliahuAaron ...probably. The order of evaluation of operands is unspecified/unsequenced, so the compiler would be allowed to evaluate the two arguments in either order, or indeed in parallel. But your comment usefully emphasises that-=is a more complicated thing than may at first appear.
– Norman Gray
yesterday
10
@NormanGray you remind me to search definition from specification, the link is c++ standard, and I find one for c#, it's from left to right.
– shingo
yesterday
1
Wait, does this mean that addition is not commutative?
– Alberto Santini
17 hours ago
3
@AlbertoSantini Because of side effects, it is not.A + Bmeans first evaluateA(might cause side effects), keep the result, then evaluateB(side effects), finally add the results.
– Jeppe Stig Nielsen
11 hours ago
|
show 2 more comments
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
9
@Bahrom: It seems to work like you claim, but why?
– Eliahu Aaron
2 days ago
12
@EliahuAaron: Because the C# spec says so. And why does the C# spec say so? Because (a) having a deterministic order of evaluation and (b) a -= b behaving like a = a - b (while evaluatingaonly once) are both widely considered to be good ideas. Would you have specified it differently? If yes, how, and why?
– Heinzi
yesterday
add a comment |
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:- Push7onto 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:- Push1onto 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:- pushesvalueonto 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.
add a comment |
You can use menu Debug → Windows → Disassembly and check what goes on in the background:
I commented the most interesting parts.
//static int value = 0;
05750449 mov ebp,esp
0575044B push edi
0575044C push esi
0575044D push ebx
0575044E sub esp,2Ch
05750451 xor edx,edx
05750453 mov dword ptr [ebp-10h],edx
05750456 mov dword ptr [ebp-1Ch],edx
05750459 cmp dword ptr ds:[15E42D8h],0
05750460 je 05750467
05750462 call 55884370
05750467 xor edx,edx
05750469 mov dword ptr ds:[15E440Ch],edx // STEP_A place 0 in ds register
somewhere
0575046F nop
05750470 lea esp,[ebp-0Ch]
05750473 pop ebx
05750474 pop esi
05750475 pop edi
05750476 pop ebp
05750477 ret
//value -= foo();
057504AB mov eax,dword ptr ds:[015E440Ch] // STEP_B places (temp) to eax. eax now contains 0
057504B0 mov dword ptr [ebp-40h],eax
057504B3 call 05750038
057504B8 mov dword ptr [ebp-44h],eax
057504BB mov eax,dword ptr [ebp-40h]
057504BE sub eax,dword ptr [ebp-44h] //STEP_C substract the return(-1) of call from the temp eax
057504C1 mov dword ptr ds:[015E440Ch],eax // STEP_D moves eax (-1) value to our ds register to some memory location
//Console.WriteLine(value);
015E04C6 mov ecx,dword ptr ds:[015E440Ch] // Self explanatory; move our ds(-1) to ecx, and then print it out to the screen.
015E04CC call 54CE8CBC
So it is true that when writing value -= foo(), it generates code something like this:
value = 0; // In the beginning STEP_A
//... main
var temp = value; //STEP_B
temp -= foo(); // STEP_C
value = temp; // STEP_D
add a comment |
I think it has something to do with how it subtracts value on the assembly level, and that causes some inconsistency in the program. I don't know if it has something to do with static or not. But from my intuition this is what happens:
Let's focus on value -= foo()
- The old
valueget saved (pushed to the stack) - The
foo()function returns1 - Now, the
valueis-7due tofoo()operation - HERE is the problem: The OLD
value(which is the one that saved earlier, which is0) subtracted with1and the result assigned to the currentvalue.
3
It's not just an accident - the C# specification specifically defines the order of execution in such a case - the compiler is not allowed to produce code that would output anything else than-1, unlike in C.
– Luaan
15 hours ago
add a comment |
value -= foo(); // value = value - foo();
foo() will return 1.
value is initially 0, so: 0 = 0 - 1.
Now the value has -1.
So the issue is with return 1.
2
This answer ignores the fact that callingfoochangesvalue.
– Theraot
yesterday
1
@Theraot: This answer is correct; the fact thatfoochangesvalueis irrelevant. Regardless of what valuesfoochanges, the fact is that subtraction in C# proceeds from left-to-right.
– Eric Lippert
4 hours ago
@EricLippert that is true, however, it is still not good explaining it.
– Theraot
4 hours ago
add a comment |
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
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
valueonto the stack. - Call the method
fooand put the result onto the stack. - Do subtraction with these two values on the stack.
- Set the result back to
valuefield.
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.
9
If you changevalue = foo() - valuetovalue = -foo() + value;in your last sentence you will get the 'expected' result-8
– Eliahu Aaron
2 days ago
4
@EliahuAaron ...probably. The order of evaluation of operands is unspecified/unsequenced, so the compiler would be allowed to evaluate the two arguments in either order, or indeed in parallel. But your comment usefully emphasises that-=is a more complicated thing than may at first appear.
– Norman Gray
yesterday
10
@NormanGray you remind me to search definition from specification, the link is c++ standard, and I find one for c#, it's from left to right.
– shingo
yesterday
1
Wait, does this mean that addition is not commutative?
– Alberto Santini
17 hours ago
3
@AlbertoSantini Because of side effects, it is not.A + Bmeans first evaluateA(might cause side effects), keep the result, then evaluateB(side effects), finally add the results.
– Jeppe Stig Nielsen
11 hours ago
|
show 2 more comments
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
valueonto the stack. - Call the method
fooand put the result onto the stack. - Do subtraction with these two values on the stack.
- Set the result back to
valuefield.
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.
9
If you changevalue = foo() - valuetovalue = -foo() + value;in your last sentence you will get the 'expected' result-8
– Eliahu Aaron
2 days ago
4
@EliahuAaron ...probably. The order of evaluation of operands is unspecified/unsequenced, so the compiler would be allowed to evaluate the two arguments in either order, or indeed in parallel. But your comment usefully emphasises that-=is a more complicated thing than may at first appear.
– Norman Gray
yesterday
10
@NormanGray you remind me to search definition from specification, the link is c++ standard, and I find one for c#, it's from left to right.
– shingo
yesterday
1
Wait, does this mean that addition is not commutative?
– Alberto Santini
17 hours ago
3
@AlbertoSantini Because of side effects, it is not.A + Bmeans first evaluateA(might cause side effects), keep the result, then evaluateB(side effects), finally add the results.
– Jeppe Stig Nielsen
11 hours ago
|
show 2 more comments
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
valueonto the stack. - Call the method
fooand put the result onto the stack. - Do subtraction with these two values on the stack.
- Set the result back to
valuefield.
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.
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
valueonto the stack. - Call the method
fooand put the result onto the stack. - Do subtraction with these two values on the stack.
- Set the result back to
valuefield.
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.
edited 12 hours ago
Peter Mortensen
14.3k19 gold badges88 silver badges116 bronze badges
14.3k19 gold badges88 silver badges116 bronze badges
answered 2 days ago
shingoshingo
5,0134 gold badges10 silver badges25 bronze badges
5,0134 gold badges10 silver badges25 bronze badges
9
If you changevalue = foo() - valuetovalue = -foo() + value;in your last sentence you will get the 'expected' result-8
– Eliahu Aaron
2 days ago
4
@EliahuAaron ...probably. The order of evaluation of operands is unspecified/unsequenced, so the compiler would be allowed to evaluate the two arguments in either order, or indeed in parallel. But your comment usefully emphasises that-=is a more complicated thing than may at first appear.
– Norman Gray
yesterday
10
@NormanGray you remind me to search definition from specification, the link is c++ standard, and I find one for c#, it's from left to right.
– shingo
yesterday
1
Wait, does this mean that addition is not commutative?
– Alberto Santini
17 hours ago
3
@AlbertoSantini Because of side effects, it is not.A + Bmeans first evaluateA(might cause side effects), keep the result, then evaluateB(side effects), finally add the results.
– Jeppe Stig Nielsen
11 hours ago
|
show 2 more comments
9
If you changevalue = foo() - valuetovalue = -foo() + value;in your last sentence you will get the 'expected' result-8
– Eliahu Aaron
2 days ago
4
@EliahuAaron ...probably. The order of evaluation of operands is unspecified/unsequenced, so the compiler would be allowed to evaluate the two arguments in either order, or indeed in parallel. But your comment usefully emphasises that-=is a more complicated thing than may at first appear.
– Norman Gray
yesterday
10
@NormanGray you remind me to search definition from specification, the link is c++ standard, and I find one for c#, it's from left to right.
– shingo
yesterday
1
Wait, does this mean that addition is not commutative?
– Alberto Santini
17 hours ago
3
@AlbertoSantini Because of side effects, it is not.A + Bmeans first evaluateA(might cause side effects), keep the result, then evaluateB(side effects), finally add the results.
– Jeppe Stig Nielsen
11 hours ago
9
9
If you change
value = foo() - value to value = -foo() + value; in your last sentence you will get the 'expected' result -8– Eliahu Aaron
2 days ago
If you change
value = foo() - value to value = -foo() + value; in your last sentence you will get the 'expected' result -8– Eliahu Aaron
2 days ago
4
4
@EliahuAaron ...probably. The order of evaluation of operands is unspecified/unsequenced, so the compiler would be allowed to evaluate the two arguments in either order, or indeed in parallel. But your comment usefully emphasises that
-= is a more complicated thing than may at first appear.– Norman Gray
yesterday
@EliahuAaron ...probably. The order of evaluation of operands is unspecified/unsequenced, so the compiler would be allowed to evaluate the two arguments in either order, or indeed in parallel. But your comment usefully emphasises that
-= is a more complicated thing than may at first appear.– Norman Gray
yesterday
10
10
@NormanGray you remind me to search definition from specification, the link is c++ standard, and I find one for c#, it's from left to right.
– shingo
yesterday
@NormanGray you remind me to search definition from specification, the link is c++ standard, and I find one for c#, it's from left to right.
– shingo
yesterday
1
1
Wait, does this mean that addition is not commutative?
– Alberto Santini
17 hours ago
Wait, does this mean that addition is not commutative?
– Alberto Santini
17 hours ago
3
3
@AlbertoSantini Because of side effects, it is not.
A + B means first evaluate A (might cause side effects), keep the result, then evaluate B (side effects), finally add the results.– Jeppe Stig Nielsen
11 hours ago
@AlbertoSantini Because of side effects, it is not.
A + B means first evaluate A (might cause side effects), keep the result, then evaluate B (side effects), finally add the results.– Jeppe Stig Nielsen
11 hours ago
|
show 2 more comments
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
9
@Bahrom: It seems to work like you claim, but why?
– Eliahu Aaron
2 days ago
12
@EliahuAaron: Because the C# spec says so. And why does the C# spec say so? Because (a) having a deterministic order of evaluation and (b) a -= b behaving like a = a - b (while evaluatingaonly once) are both widely considered to be good ideas. Would you have specified it differently? If yes, how, and why?
– Heinzi
yesterday
add a 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
9
@Bahrom: It seems to work like you claim, but why?
– Eliahu Aaron
2 days ago
12
@EliahuAaron: Because the C# spec says so. And why does the C# spec say so? Because (a) having a deterministic order of evaluation and (b) a -= b behaving like a = a - b (while evaluatingaonly once) are both widely considered to be good ideas. Would you have specified it differently? If yes, how, and why?
– Heinzi
yesterday
add a 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
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
edited 2 days ago
answered 2 days ago
BahromBahrom
1,7559 silver badges17 bronze badges
1,7559 silver badges17 bronze badges
9
@Bahrom: It seems to work like you claim, but why?
– Eliahu Aaron
2 days ago
12
@EliahuAaron: Because the C# spec says so. And why does the C# spec say so? Because (a) having a deterministic order of evaluation and (b) a -= b behaving like a = a - b (while evaluatingaonly once) are both widely considered to be good ideas. Would you have specified it differently? If yes, how, and why?
– Heinzi
yesterday
add a comment |
9
@Bahrom: It seems to work like you claim, but why?
– Eliahu Aaron
2 days ago
12
@EliahuAaron: Because the C# spec says so. And why does the C# spec say so? Because (a) having a deterministic order of evaluation and (b) a -= b behaving like a = a - b (while evaluatingaonly once) are both widely considered to be good ideas. Would you have specified it differently? If yes, how, and why?
– Heinzi
yesterday
9
9
@Bahrom: It seems to work like you claim, but why?
– Eliahu Aaron
2 days ago
@Bahrom: It seems to work like you claim, but why?
– Eliahu Aaron
2 days ago
12
12
@EliahuAaron: Because the C# spec says so. And why does the C# spec say so? Because (a) having a deterministic order of evaluation and (b) a -= b behaving like a = a - b (while evaluating
a only once) are both widely considered to be good ideas. Would you have specified it differently? If yes, how, and why?– Heinzi
yesterday
@EliahuAaron: Because the C# spec says so. And why does the C# spec say so? Because (a) having a deterministic order of evaluation and (b) a -= b behaving like a = a - b (while evaluating
a only once) are both widely considered to be good ideas. Would you have specified it differently? If yes, how, and why?– Heinzi
yesterday
add a comment |
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:- Push7onto 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:- Push1onto 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:- pushesvalueonto 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.
add a comment |
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:- Push7onto 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:- Push1onto 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:- pushesvalueonto 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.
add a comment |
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:- Push7onto 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:- Push1onto 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:- pushesvalueonto 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.
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:- Push7onto 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:- Push1onto 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:- pushesvalueonto 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.
edited 12 hours ago
Peter Mortensen
14.3k19 gold badges88 silver badges116 bronze badges
14.3k19 gold badges88 silver badges116 bronze badges
answered 2 days ago
SᴇMSᴇM
5,4262 gold badges16 silver badges32 bronze badges
5,4262 gold badges16 silver badges32 bronze badges
add a comment |
add a comment |
You can use menu Debug → Windows → Disassembly and check what goes on in the background:
I commented the most interesting parts.
//static int value = 0;
05750449 mov ebp,esp
0575044B push edi
0575044C push esi
0575044D push ebx
0575044E sub esp,2Ch
05750451 xor edx,edx
05750453 mov dword ptr [ebp-10h],edx
05750456 mov dword ptr [ebp-1Ch],edx
05750459 cmp dword ptr ds:[15E42D8h],0
05750460 je 05750467
05750462 call 55884370
05750467 xor edx,edx
05750469 mov dword ptr ds:[15E440Ch],edx // STEP_A place 0 in ds register
somewhere
0575046F nop
05750470 lea esp,[ebp-0Ch]
05750473 pop ebx
05750474 pop esi
05750475 pop edi
05750476 pop ebp
05750477 ret
//value -= foo();
057504AB mov eax,dword ptr ds:[015E440Ch] // STEP_B places (temp) to eax. eax now contains 0
057504B0 mov dword ptr [ebp-40h],eax
057504B3 call 05750038
057504B8 mov dword ptr [ebp-44h],eax
057504BB mov eax,dword ptr [ebp-40h]
057504BE sub eax,dword ptr [ebp-44h] //STEP_C substract the return(-1) of call from the temp eax
057504C1 mov dword ptr ds:[015E440Ch],eax // STEP_D moves eax (-1) value to our ds register to some memory location
//Console.WriteLine(value);
015E04C6 mov ecx,dword ptr ds:[015E440Ch] // Self explanatory; move our ds(-1) to ecx, and then print it out to the screen.
015E04CC call 54CE8CBC
So it is true that when writing value -= foo(), it generates code something like this:
value = 0; // In the beginning STEP_A
//... main
var temp = value; //STEP_B
temp -= foo(); // STEP_C
value = temp; // STEP_D
add a comment |
You can use menu Debug → Windows → Disassembly and check what goes on in the background:
I commented the most interesting parts.
//static int value = 0;
05750449 mov ebp,esp
0575044B push edi
0575044C push esi
0575044D push ebx
0575044E sub esp,2Ch
05750451 xor edx,edx
05750453 mov dword ptr [ebp-10h],edx
05750456 mov dword ptr [ebp-1Ch],edx
05750459 cmp dword ptr ds:[15E42D8h],0
05750460 je 05750467
05750462 call 55884370
05750467 xor edx,edx
05750469 mov dword ptr ds:[15E440Ch],edx // STEP_A place 0 in ds register
somewhere
0575046F nop
05750470 lea esp,[ebp-0Ch]
05750473 pop ebx
05750474 pop esi
05750475 pop edi
05750476 pop ebp
05750477 ret
//value -= foo();
057504AB mov eax,dword ptr ds:[015E440Ch] // STEP_B places (temp) to eax. eax now contains 0
057504B0 mov dword ptr [ebp-40h],eax
057504B3 call 05750038
057504B8 mov dword ptr [ebp-44h],eax
057504BB mov eax,dword ptr [ebp-40h]
057504BE sub eax,dword ptr [ebp-44h] //STEP_C substract the return(-1) of call from the temp eax
057504C1 mov dword ptr ds:[015E440Ch],eax // STEP_D moves eax (-1) value to our ds register to some memory location
//Console.WriteLine(value);
015E04C6 mov ecx,dword ptr ds:[015E440Ch] // Self explanatory; move our ds(-1) to ecx, and then print it out to the screen.
015E04CC call 54CE8CBC
So it is true that when writing value -= foo(), it generates code something like this:
value = 0; // In the beginning STEP_A
//... main
var temp = value; //STEP_B
temp -= foo(); // STEP_C
value = temp; // STEP_D
add a comment |
You can use menu Debug → Windows → Disassembly and check what goes on in the background:
I commented the most interesting parts.
//static int value = 0;
05750449 mov ebp,esp
0575044B push edi
0575044C push esi
0575044D push ebx
0575044E sub esp,2Ch
05750451 xor edx,edx
05750453 mov dword ptr [ebp-10h],edx
05750456 mov dword ptr [ebp-1Ch],edx
05750459 cmp dword ptr ds:[15E42D8h],0
05750460 je 05750467
05750462 call 55884370
05750467 xor edx,edx
05750469 mov dword ptr ds:[15E440Ch],edx // STEP_A place 0 in ds register
somewhere
0575046F nop
05750470 lea esp,[ebp-0Ch]
05750473 pop ebx
05750474 pop esi
05750475 pop edi
05750476 pop ebp
05750477 ret
//value -= foo();
057504AB mov eax,dword ptr ds:[015E440Ch] // STEP_B places (temp) to eax. eax now contains 0
057504B0 mov dword ptr [ebp-40h],eax
057504B3 call 05750038
057504B8 mov dword ptr [ebp-44h],eax
057504BB mov eax,dword ptr [ebp-40h]
057504BE sub eax,dword ptr [ebp-44h] //STEP_C substract the return(-1) of call from the temp eax
057504C1 mov dword ptr ds:[015E440Ch],eax // STEP_D moves eax (-1) value to our ds register to some memory location
//Console.WriteLine(value);
015E04C6 mov ecx,dword ptr ds:[015E440Ch] // Self explanatory; move our ds(-1) to ecx, and then print it out to the screen.
015E04CC call 54CE8CBC
So it is true that when writing value -= foo(), it generates code something like this:
value = 0; // In the beginning STEP_A
//... main
var temp = value; //STEP_B
temp -= foo(); // STEP_C
value = temp; // STEP_D
You can use menu Debug → Windows → Disassembly and check what goes on in the background:
I commented the most interesting parts.
//static int value = 0;
05750449 mov ebp,esp
0575044B push edi
0575044C push esi
0575044D push ebx
0575044E sub esp,2Ch
05750451 xor edx,edx
05750453 mov dword ptr [ebp-10h],edx
05750456 mov dword ptr [ebp-1Ch],edx
05750459 cmp dword ptr ds:[15E42D8h],0
05750460 je 05750467
05750462 call 55884370
05750467 xor edx,edx
05750469 mov dword ptr ds:[15E440Ch],edx // STEP_A place 0 in ds register
somewhere
0575046F nop
05750470 lea esp,[ebp-0Ch]
05750473 pop ebx
05750474 pop esi
05750475 pop edi
05750476 pop ebp
05750477 ret
//value -= foo();
057504AB mov eax,dword ptr ds:[015E440Ch] // STEP_B places (temp) to eax. eax now contains 0
057504B0 mov dword ptr [ebp-40h],eax
057504B3 call 05750038
057504B8 mov dword ptr [ebp-44h],eax
057504BB mov eax,dword ptr [ebp-40h]
057504BE sub eax,dword ptr [ebp-44h] //STEP_C substract the return(-1) of call from the temp eax
057504C1 mov dword ptr ds:[015E440Ch],eax // STEP_D moves eax (-1) value to our ds register to some memory location
//Console.WriteLine(value);
015E04C6 mov ecx,dword ptr ds:[015E440Ch] // Self explanatory; move our ds(-1) to ecx, and then print it out to the screen.
015E04CC call 54CE8CBC
So it is true that when writing value -= foo(), it generates code something like this:
value = 0; // In the beginning STEP_A
//... main
var temp = value; //STEP_B
temp -= foo(); // STEP_C
value = temp; // STEP_D
edited 12 hours ago
Peter Mortensen
14.3k19 gold badges88 silver badges116 bronze badges
14.3k19 gold badges88 silver badges116 bronze badges
answered 2 days ago
kovirolikoviroli
8365 silver badges16 bronze badges
8365 silver badges16 bronze badges
add a comment |
add a comment |
I think it has something to do with how it subtracts value on the assembly level, and that causes some inconsistency in the program. I don't know if it has something to do with static or not. But from my intuition this is what happens:
Let's focus on value -= foo()
- The old
valueget saved (pushed to the stack) - The
foo()function returns1 - Now, the
valueis-7due tofoo()operation - HERE is the problem: The OLD
value(which is the one that saved earlier, which is0) subtracted with1and the result assigned to the currentvalue.
3
It's not just an accident - the C# specification specifically defines the order of execution in such a case - the compiler is not allowed to produce code that would output anything else than-1, unlike in C.
– Luaan
15 hours ago
add a comment |
I think it has something to do with how it subtracts value on the assembly level, and that causes some inconsistency in the program. I don't know if it has something to do with static or not. But from my intuition this is what happens:
Let's focus on value -= foo()
- The old
valueget saved (pushed to the stack) - The
foo()function returns1 - Now, the
valueis-7due tofoo()operation - HERE is the problem: The OLD
value(which is the one that saved earlier, which is0) subtracted with1and the result assigned to the currentvalue.
3
It's not just an accident - the C# specification specifically defines the order of execution in such a case - the compiler is not allowed to produce code that would output anything else than-1, unlike in C.
– Luaan
15 hours ago
add a comment |
I think it has something to do with how it subtracts value on the assembly level, and that causes some inconsistency in the program. I don't know if it has something to do with static or not. But from my intuition this is what happens:
Let's focus on value -= foo()
- The old
valueget saved (pushed to the stack) - The
foo()function returns1 - Now, the
valueis-7due tofoo()operation - HERE is the problem: The OLD
value(which is the one that saved earlier, which is0) subtracted with1and the result assigned to the currentvalue.
I think it has something to do with how it subtracts value on the assembly level, and that causes some inconsistency in the program. I don't know if it has something to do with static or not. But from my intuition this is what happens:
Let's focus on value -= foo()
- The old
valueget saved (pushed to the stack) - The
foo()function returns1 - Now, the
valueis-7due tofoo()operation - HERE is the problem: The OLD
value(which is the one that saved earlier, which is0) subtracted with1and the result assigned to the currentvalue.
edited 12 hours ago
Peter Mortensen
14.3k19 gold badges88 silver badges116 bronze badges
14.3k19 gold badges88 silver badges116 bronze badges
answered 2 days ago
molmol
303 bronze badges
303 bronze badges
3
It's not just an accident - the C# specification specifically defines the order of execution in such a case - the compiler is not allowed to produce code that would output anything else than-1, unlike in C.
– Luaan
15 hours ago
add a comment |
3
It's not just an accident - the C# specification specifically defines the order of execution in such a case - the compiler is not allowed to produce code that would output anything else than-1, unlike in C.
– Luaan
15 hours ago
3
3
It's not just an accident - the C# specification specifically defines the order of execution in such a case - the compiler is not allowed to produce code that would output anything else than
-1, unlike in C.– Luaan
15 hours ago
It's not just an accident - the C# specification specifically defines the order of execution in such a case - the compiler is not allowed to produce code that would output anything else than
-1, unlike in C.– Luaan
15 hours ago
add a comment |
value -= foo(); // value = value - foo();
foo() will return 1.
value is initially 0, so: 0 = 0 - 1.
Now the value has -1.
So the issue is with return 1.
2
This answer ignores the fact that callingfoochangesvalue.
– Theraot
yesterday
1
@Theraot: This answer is correct; the fact thatfoochangesvalueis irrelevant. Regardless of what valuesfoochanges, the fact is that subtraction in C# proceeds from left-to-right.
– Eric Lippert
4 hours ago
@EricLippert that is true, however, it is still not good explaining it.
– Theraot
4 hours ago
add a comment |
value -= foo(); // value = value - foo();
foo() will return 1.
value is initially 0, so: 0 = 0 - 1.
Now the value has -1.
So the issue is with return 1.
2
This answer ignores the fact that callingfoochangesvalue.
– Theraot
yesterday
1
@Theraot: This answer is correct; the fact thatfoochangesvalueis irrelevant. Regardless of what valuesfoochanges, the fact is that subtraction in C# proceeds from left-to-right.
– Eric Lippert
4 hours ago
@EricLippert that is true, however, it is still not good explaining it.
– Theraot
4 hours ago
add a comment |
value -= foo(); // value = value - foo();
foo() will return 1.
value is initially 0, so: 0 = 0 - 1.
Now the value has -1.
So the issue is with return 1.
value -= foo(); // value = value - foo();
foo() will return 1.
value is initially 0, so: 0 = 0 - 1.
Now the value has -1.
So the issue is with return 1.
edited 12 hours ago
Peter Mortensen
14.3k19 gold badges88 silver badges116 bronze badges
14.3k19 gold badges88 silver badges116 bronze badges
answered 2 days ago
Arun Pandian kArun Pandian k
93 bronze badges
93 bronze badges
2
This answer ignores the fact that callingfoochangesvalue.
– Theraot
yesterday
1
@Theraot: This answer is correct; the fact thatfoochangesvalueis irrelevant. Regardless of what valuesfoochanges, the fact is that subtraction in C# proceeds from left-to-right.
– Eric Lippert
4 hours ago
@EricLippert that is true, however, it is still not good explaining it.
– Theraot
4 hours ago
add a comment |
2
This answer ignores the fact that callingfoochangesvalue.
– Theraot
yesterday
1
@Theraot: This answer is correct; the fact thatfoochangesvalueis irrelevant. Regardless of what valuesfoochanges, the fact is that subtraction in C# proceeds from left-to-right.
– Eric Lippert
4 hours ago
@EricLippert that is true, however, it is still not good explaining it.
– Theraot
4 hours ago
2
2
This answer ignores the fact that calling
foo changes value.– Theraot
yesterday
This answer ignores the fact that calling
foo changes value.– Theraot
yesterday
1
1
@Theraot: This answer is correct; the fact that
foo changes value is irrelevant. Regardless of what values foo changes, the fact is that subtraction in C# proceeds from left-to-right.– Eric Lippert
4 hours ago
@Theraot: This answer is correct; the fact that
foo changes value is irrelevant. Regardless of what values foo changes, the fact is that subtraction in C# proceeds from left-to-right.– Eric Lippert
4 hours ago
@EricLippert that is true, however, it is still not good explaining it.
– Theraot
4 hours ago
@EricLippert that is true, however, it is still not good explaining it.
– Theraot
4 hours ago
add a comment |
8
@pappbence96 which is exactly what he expects, but isn't getting.
– TvanB
2 days ago
46
FYI, this has nothing to do with static.
– Ahmed Abdelhameed
2 days ago
7
Debuged this already , when method ends, value = -7, but step next it magically changed on "-1". Thas the problem which can't understand
– EmerG
2 days ago
13
value -= foo()is the same asvalue = current value of value (0) - foo() which returns 1, which is the same asvalue = 0 - 1.foo()does decrementvaluebut only after you've referenced it in the calculation that callsfoo(). Bad explanations have made it difficult to understand, but that's it in a nutshell.– Archer
2 days ago
2
Statements like
i += i++;are inherently ambiguous in meaning. Some languages have legalese in place that makes such statements well-defined, other languages (infamously the C family) just say: "The order of operand evaluation is undefined." It doesn't matter what category your language falls in, code that's ambiguous in this way should not be written as it's hard to understand.– cmaster
yesterday