委托内部循环如何理解本地和循环变量之间的区别

Vla*_*yan 0 c# closures loops

看看这段代码

    List<Action> actions = new List<Action>();
    for (int variable = 0; variable < 5; ++variable)
        {
            int myLocalVariable = variable;
            actions.Add(() => Console.WriteLine(myLocalVariable));
        }
    actions.ForEach(s => s.Invoke());
    Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)

输出为0 1 2 3 4

看一下IL代码,我倾向于认为编译器只创建了一个myLocalVariable实例.这一事实也证实了在循环中使用局部变量的良好实践.

那么如何委托inside actions.Add()存储循环变量的"最新"版本.

Jon*_*eet 5

看一下IL代码,我倾向于认为编译器只创建了一个myLocalVariable实例.

不.C#语言规范清楚地表明变量是在循环的每次迭代中实例化的 - 因此每次迭代都有一个单独的变量,它们是分别捕获的.

从C#5规范的7.5.15.2节:

当执行进入变量的范围时,认为局部变量被实例化.例如,当调用以下方法时,对于循环的每次迭代,局部变量x被实例化并初始化三次 - 一次.

static void F() {
    for (int i = 0; i < 3; i++) {
        int x = i * 2 + 1;
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,在循环外部移动x的声明会导致单个实例化 x

...

当没有捕获时,无法准确地观察局部变量被实例化的频率 - 因为实例化的生命期是不相交的,所以每个瞬时可以简单地使用相同的存储位置.但是,当匿名函数捕获局部变量时,实例化的效果变得明显.