hol*_*hen 5 c# closures for-loop
在C#中尝试使用闭包时,我发现如果它们在循环中捕获迭代器变量,它们会出乎意料地工作.
var actions = new List<Action>();
foreach (int i in new[] { 1, 2 })
actions.Add(() => Console.WriteLine(i));
for (int i = 3; i <= 4; i++)
actions.Add(() => Console.WriteLine(i));
foreach (var action in actions)
action();
Run Code Online (Sandbox Code Playgroud)
上面的代码产生了一个奇怪的结果(我使用的是.NET 4.5编译器):
1
2
5
5
Run Code Online (Sandbox Code Playgroud)
为什么i两个几乎相同的循环捕获的值不同?
在C#5及更高版本中,foreach循环为循环的每次迭代声明一个单独的 i变量.因此每个闭包捕获一个单独的变量,您可以看到预期的结果.
在for循环中,你只有一个单一的 i变量,它是由所有的封闭拍摄,并且修改循环的进展-所以你的时候调用的代表,你看,单变量的最终值.
在C#2,3和4中,foreach循环也表现出来,这基本上不是所希望的行为,因此它在C#5中得到修复.
for如果在循环体的范围内引入新变量,则可以在循环中实现相同的效果:
for (int i = 3; i <= 4; i++)
{
int copy = i;
actions.Add(() => Console.WriteLine(copy));
}
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请阅读Eric Lippert的博文,"关闭循环变量被视为有害" - 第1 部分,第2部分.