c# 5.0中的捕获闭包(循环变量)

本文关键字:闭包 循环 变量 | 更新日期: 2023-09-27 18:11:09

这在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循环的问题)?

c# 5.0中的捕获闭包(循环变量)

这背后的原因是什么?

我假设你的意思是"为什么不改变for循环?"

答案是,对于for循环,现有的行为是完全合理的。如果将for循环分解为:

    <
  • 初始化/gh>
  • 迭代器
  • 身体

…那么循环大致为:

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

(当然,iterator也在continue;语句的末尾执行)

初始化部分逻辑上只发生一次,所以只有一个"变量实例化"是完全合乎逻辑的。此外,在循环的每次迭代中,变量没有自然的"初始"值——没有必要说for循环必须具有这样的形式:在初始化器中声明一个变量,在条件中测试它,然后在迭代器中修改它。你期望这样的循环做什么:

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

foreach循环相比,看起来就像你为每次迭代声明了一个单独的变量。见鬼,变量是只读的,这使得认为它是一个在迭代之间更改的变量更加 奇怪。将foreach循环看作是在每次迭代中声明一个新的只读变量,其值取自迭代器,这是完全有意义的。