看一下代码片段
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();
输出为0 1 2 3 4
查看IL代码我倾向于认为编译器只创建了一个myLocalVariable实例。这一事实也证实了在循环中使用局部变量的良好实践。
那么如何委托内部的行动。添加()存储&#34;最新的&#34;循环变量的版本。
答案 0 :(得分: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; ... } }
但是,在循环外移动x的声明会导致
的单个实例化x
...
如果没有捕获,则无法准确地观察实例化局部变量的频率 - 因为实例化的生命周期是不相交的,所以每个瞬时都可以简单地使用相同的存储位置。但是,当匿名函数捕获局部变量时,实例化的效果变得明显。