为啥在 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? - forforeach 中详细讨论了这种行为(和投诉),在 C#4 及之前有同样的“问题”,在 C 中为 foreach “修复” #5.

我认为可以公平地说,所有人都对这个决定感到遗憾。这是 C# 中最糟糕的“陷阱”之一,我们将采取重大更改来修复它。在 C# 5 中,foreach 循环变量在逻辑上将位于循环主体内,因此闭包每次都会获得一个新副本。 - 埃里克·利珀特

【讨论】:

@ErikFunkenbusch 哦,是的。谢谢。我忘了更改所有出现的原始i

以上是关于为啥在 Array.ForEach 输出 333 而不是 0112? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

php while循环和foreach循环 mysql_fetch_array()

为啥我在 Python 中没有得到 333

基本内爆 foreach

为啥FlashFXP连接不了,请教各位高手啊!!!

Swift:$0 在 Array.forEach 中是如何工作的?

JavaScript----Array.foreach()