在C#5.0中捕获的闭包(循环variables)

这工作正常(意味着如预期)在C#5.0中:

var actions = new List<Action>(); foreach (var i in Enumerable.Range(0, 10)) { actions.Add(() => Console.WriteLine(i)); } foreach (var act in actions) act(); 

打印0到9.但是这个10次显示10次:

 var actions = new List<Action>(); for (var i = 0; i < 10; i++) { actions.Add(() => Console.WriteLine(i)); } foreach (var act in actions) act(); 

问题:这是我们在5.0之前的C#版本中遇到的问题; 所以我们必须使用循环本地占位符来封闭,现在在C#5.0中,在“foreach”循环中已经修复了。 但不是在“for”循环中!

这背后的原因是什么(也没有解决for循环的问题)?

这背后的推理是什么?

我会假设你的意思是“为什么不for循环而改变呢?”

答案是for循环,现有的行为是非常有意义的。 如果你打开一个for循环到:

  • 初始化
  • 条件
  • 迭代器
  • 身体

…那么循环大概是:

 { initializer; while (condition) { body; iterator; } } 

(当然,除了iteratorcontinue;语句结束时执行)。

初始化部分逻辑上只发生一次,所以只有一个“variables实例化”是完全合乎逻辑的。 此外,在循环的每次迭代中,variables没有自然的“初始”值 – 没有什么可以说for循环必须是在初始化器中声明variables的forms,在条件中testing它并在迭代器。 你会期待什么循环这样做:

 for (int i = 0, j = 10; i < j; i++) { if (someCondition) { j++; } actions.Add(() => Console.WriteLine(i, j)); } 

将它与foreach循环比较, 看起来像是为每个迭代声明一个单独的variables。 哎呀,这个variables是只读的, 令人觉得奇怪的是,它是一个在迭代之间变化的variables。 将foreach循环看作是在每次迭代中声明一个新的只读variables,并从迭代器中获取其值,这是非常有意义的。