c#在Lambda表达式中声明变量

Mou*_*hyi 11 c# lambda

下面的代码输出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)

Dav*_*eau 7

这称为"访问修改后的闭包".基本上,只有一个i变量,而且所有三个lambd都指的是它.最后,一个i变量已递增到3,因此打印所有三个动作3.(注意,int loopScopedi = i在lambda中,只有在稍后调用lambda时才会运行.)

在第二个版本中,您要创建一个新的int loopScopedi每次迭代,并将其设置为当前值i,这是012,每次迭代.

您可以尝试想象内联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)