下面的代码片段将输出数字“10”十次:
\n\ndelegate void Printer();\n\nstatic void Main()\n{\n List<Printer> printers = new List<Printer>();\n for (int i = 0; i < 10; i++)\n {\n printers.Add(delegate { Console.WriteLine(i); });\n }\n\n foreach (var printer in printers)\n {\n printer();\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这是因为(取自https://www.toptal.com/c-sharp/interview-questions#iquestion-90455):
\n\n\n\n\n“委托被添加到 for 循环中,\xe2\x80\x9creference\xe2\x80\x9d 到 i 被存储,\n 而不是值本身。因此,在我们退出循环后,\n 变量 i 已被存储设置为 10,因此当每个委托被调用时,传递给所有委托的值都是 10。”
\n
我的问题是:为什么存储对 i 的“引用”?
\n\n\n\n这是因为“委托被添加到 for 循环中,并且 \xe2\x80\x9creference\xe2\x80\x9d 到 i 被存储
\n
不,这不是问题。问题在于提取委托和引用值的方式。这就是所谓的封闭。从循环中提取委托,并且由于闭包在循环之后i运行,因此仅保留最后一个值。(如果您中途调用它,它将返回当时的值)。
请参阅这篇博客文章,委托最终如何在看似错误的位置进行编译。
\n\n这是它用来演示该问题的代码:
\n\nFunc func1 = null;\n\nProgram.<>c__DisplayClass2 class1 = new Program.<>c__DisplayClass2(); // <-- problem\n\nclass1.i = 0;\n\nwhile (class1.i < count)\n{\n if (func1 == null) // <-- more problems to follow\n {\n func1 = new Func(class1.<fillFunc>b__0); // <-- yikes: just one func!\n }\n\n Program.funcArr[class1.i] = func1;\n class1.i++; // <-- and just one i\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
240 次 |
| 最近记录: |