下面的代码输出33而不是012.我不明白为什么在每次迭代中没有捕获新变量loopScopedi而不是捕获相同的变量.
Action[] actions = new Action[3];
for (int i = 0; i < 3; i++)
{
actions [i] = () => {int loopScopedi = i; Console.Write (loopScopedi);};
}
foreach (Action a in actions) a(); // 333
Run Code Online (Sandbox Code Playgroud)
Hopwever,这段代码产生012.两者之间有什么区别?
Action[] actions = new Action[3];
for (int i = 0; i < 3; i++)
{
int loopScopedi = i;
actions [i] = () => Console.Write (loopScopedi);
}
foreach (Action a in actions) a(); // 012
Run Code Online (Sandbox Code Playgroud)
这称为"访问修改后的闭包".基本上,只有一个i变量,而且所有三个lambd都指的是它.最后,一个i变量已递增到3,因此打印所有三个动作3.(注意,int loopScopedi = i在lambda中,只有在稍后调用lambda时才会运行.)
在第二个版本中,您要创建一个新的int loopScopedi每次迭代,并将其设置为当前值i,这是0和1和2,每次迭代.
您可以尝试想象内联lambda以更清楚地了解正在发生的事情:
foreach (Action a in actions)
{
int loopScopedi = i; // i == 3, since this is after the for loop
Console.Write(loopScopedi); // always outputs 3
}
Run Code Online (Sandbox Code Playgroud)
与:
foreach (Action a in actions)
{
// normally you could not refer to loopScopedi here, but the lambda lets you
// you have "captured" a reference to the loopScopedi variables in the lambda
// there are three loopScopedis that each saved a different value of i
// at the time that it was allocated
Console.Write(loopScopedi); // outputs 0, 1, 2
}
Run Code Online (Sandbox Code Playgroud)