c# - Why does using the await operator for the second argument to a method affect the value of the first argument? -
the following c# program produces unexpected output. expect see:
value1: 25, value2: 10
value1: 10, value2: 25
but instead see
value1: 0, value2: 10
value1: 10, value2: 25
namespace consoleapplication4 { class program { static void main(string[] args) { dowork().wait(); console.readline(); } private async static task dowork() { someclass foo = new someclass() { myvalue = 25.0f }; printtwovalues(foo.myvalue, await getvalue()); printtwovalues(await getvalue(), foo.myvalue); } static void printtwovalues(float value1, float value2) { console.writeline("value1: {0}, value2: {1}", value1, value2); } static task<float> getvalue() { return task.factory.startnew(() => { return 10.0f; }); } class someclass { private float myvalue; public float myvalue { { return this.myvalue; } set { this.myvalue = value; } } } } }
can explain me why using "await" operator in expression second argument printtwovalues
method seems affecting value of first argument?
my guess must have fact argument list evaluated left-to-right. in first call printtwovalues
i'm guessing return value someclass.myvalue
gets pushed onto stack. execution continues getvalue
starts task , exits. dowork
exits , schedules continuation call printtwovalues
when continuation runs value had gotten pushed on stack somehow lost , reverted default value.
while there simple ways workaround problem, storing arguments in temporary variables before passing them printtwovalues
method, i'm curious why behavior occurring.
note: i'm using visual studio 2013, update 5. i'm building console application targeting .net framework 4.5 , running on windows 10 enterprise.
i've tested code both c#5 compiler , c#6 compiler using respectively linqpad 4 , linqpad 5 , reproduce issue.
this looks compiler bug of c#5 compiler, because when decomplied both versions .net reflector 9, got different code:
c#5:
private async static task dowork() { float myvalue; someclass foo = new someclass { myvalue = 25f }; float introduced6 = await getvalue(); printtwovalues(myvalue, introduced6); float introduced7 = await getvalue(); printtwovalues(introduced7, foo.myvalue); }
c#6:
private async static task dowork() { someclass foo = new someclass { myvalue = 25f }; float myvalue = foo.myvalue; float num2 = await getvalue(); float asyncvariable1 = num2; printtwovalues(myvalue, asyncvariable1); num2 = await getvalue(); float asyncvariable2 = num2; printtwovalues(asyncvariable2, foo.myvalue); }
notice that, c#5, myvalue
variable declared before declaration of of foo
, never initialized before first call printtwovalues
.
Comments
Post a Comment