为什么存储对 int (而不是值)的“引用”?

Not*_*arp 0 c# delegates

下面的代码片段将输出数字“10”十次:

\n\n
delegate 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}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是因为(取自https://www.toptal.com/c-sharp/interview-questions#iquestion-90455):

\n\n
\n

“委托被添加到 for 循环中,\xe2\x80\x9creference\xe2\x80\x9d 到 i 被存储,\n 而不是值本身。因此,在我们退出循环后,\n 变量 i 已被存储设置为 10,因此当每个委托被调用时,传递给所有委托的值都是 10。”

\n
\n\n

我的问题是:为什么存储对 i 的“引用”?

\n

Pat*_*man 6

\n

这是因为“委托被添加到 for 循环中,并且 \xe2\x80\x9creference\xe2\x80\x9d 到 i 被存储

\n
\n\n

不,这不是问题。问题在于提取委托和引用值的方式。这就是所谓的封闭。从循环中提取委托,并且由于闭包在循环之后i运行,因此仅保留最后一个值。(如果您中途调用它,它将返回当时的值)。

\n\n

请参阅这篇博客文章,委托最终如何在看似错误的位置进行编译。

\n\n

这是它用来演示该问题的代码:

\n\n
Func 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}\n
Run Code Online (Sandbox Code Playgroud)\n