为什么下面的代码输出333不是012? 我认为代码是如此简单,我检查和检查,仔细检查,三重检查,还不能得到答案。任何人都可以帮助我吗?
Action[] tmp = new Action[3];
for (int i = 0; i < tmp.Length; i++)
{
tmp[i] = () => Console.WriteLine(i);
}
Array.ForEach(tmp, m => m());
Console.Read();
答案 0 :(得分:1)
这是因为原始代码中只有一个 i
变量,因为for
不引入新变量&#34;每个循环&#34;并且相同的变量在所有闭包中被关闭!因此,在循环之后执行任何函数之前,相同的(i
)变量被赋予最后一个值(3)。
与下面的代码比较,确保在每个闭包中绑定 new 变量(这是一种罕见的情况,我使用下划线表示局部变量&#34;有趣的东西&#34;正在发生):
for (int _i = 0; _i < tmp.Length; _i++)
{
int i = _i; // NEW/fresh variable, i, introduced each loop
tmp[i] = () => Console.WriteLine(i);
}
Is there a reason for C#'s reuse of the variable in a foreach? - for
中详细讨论了这种行为(和投诉),foreach
也有同样的问题&#34;在C#4和之前,这是&#34;固定&#34;对于C#5中的foreach
。
我认为可以公平地说这一切都让人感到后悔。这是最糟糕的&#34;陷阱之一&#34;在C#中,我们将采取重大改变来解决它。在C#5中,foreach循环变量将在逻辑上位于循环体内,因此闭包每次都会得到一个新的副本。 - Eric Lippert
答案 1 :(得分:1)
您应该将代码更改为:
Action[] tmp = new Action[3];
for (int i = 0; i < tmp.Length; i++)
{
int j = i;
tmp[i] = () => Console.WriteLine(j);
}
Array.ForEach(tmp, m => m());
Console.Read();
原因是封闭是巢
更详细的信息请看这些链接: Is there a reason for C#'s reuse of the variable in a foreach? http://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/