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



看看代码的这个片段

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的一个实例。这个事实也证实了在循环中使用局部变量的良好做法。

那么如何委派内部行动呢。Add()存储循环变量的"最新"版本。

查看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的单个实例化

如果没有捕获,就无法准确观察局部变量实例化的频率——因为实例化的寿命是不相交的,所以每个实例化都可以简单地使用相同的存储位置。然而,当匿名函数捕获局部变量时,实例化的效果会变得明显。

最新更新