Why does this output 333 not 0112 at Array.ForEach?
为什么下面的代码ouput 333而不是012?我觉得代码太简单了,我检查,再检查,三次检查,还不能得到答案。有人能帮我吗?
1 2 3 4 5 6 7 8 9 10 | 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 2 3 4 5 6 7 8 9 10 11 | 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(); |
原因是关闭是巢
更多详细信息,请参见以下链接:是否有理由在foreach中重新使用变量c?http://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/
这是因为原始代码中只有一个
与确保在每个闭包中绑定新变量的以下代码相比(这是一种罕见的情况,在这种情况下,我使用下划线表示局部变量正在发生"有趣的事情"):
1 2 3 4 5 | for (int _i = 0; _i < tmp.Length; _i++) { int i = _i; // NEW/fresh variable, i, introduced each loop tmp[i] = () => Console.WriteLine(i); } |
这一行为(以及对它的抱怨)在foreach中有没有详细讨论过C重用变量的原因?-
I think it is fair to say that all regret that decision. This is one of the worst"gotchas" in C#, and we are going to take the breaking change to fix it. In C# 5 the foreach loop variable will be logically inside the body of the loop, and therefore closures will get a fresh copy every time. - Eric Lippert