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