为啥在 Array.ForEach 输出 333 而不是 0112? [复制]
Posted
技术标签:
【中文标题】为啥在 Array.ForEach 输出 333 而不是 0112? [复制]【英文标题】:Why does this output 333 not 0112 at Array.ForEach? [duplicate]为什么在 Array.ForEach 输出 333 而不是 0112? [复制] 【发布时间】:2014-06-19 19:19:12 【问题描述】:为什么下面的代码输出 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();
【问题讨论】:
谢谢!你可能是对的。 【参考方案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/
【讨论】:
非常感谢。使用您的代码,我立即得到正确的结果。甚至您的链接也与其他链接相同。但是您是提供代码的人。所以我接受你的回答。但我也感谢其他人。【参考方案2】:发生这种情况是因为原始代码中只有 一个 i
变量,因为 for
not 引入了一个新变量“每个循环”并且 same 变量在所有闭包中都被关闭了!因此,same (i
) 变量在循环后执行任何函数之前被分配最后一个值 (3)。
与以下代码比较,它确保在每个闭包中绑定一个 new 变量(这是一种罕见的情况,我使用下划线作为局部变量来显示“发生了一些有趣的事情”):
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
中详细讨论了这种行为(和投诉),在 C#4 及之前有同样的“问题”,在 C 中为 foreach
“修复” #5.
我认为可以公平地说,所有人都对这个决定感到遗憾。这是 C# 中最糟糕的“陷阱”之一,我们将采取重大更改来修复它。在 C# 5 中,foreach 循环变量在逻辑上将位于循环主体内,因此闭包每次都会获得一个新副本。 - 埃里克·利珀特
【讨论】:
@ErikFunkenbusch 哦,是的。谢谢。我忘了更改所有出现的原始i
。以上是关于为啥在 Array.ForEach 输出 333 而不是 0112? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
php while循环和foreach循环 mysql_fetch_array()