【问题标题】:cannot understand lamda expression output无法理解 lambda 表达式输出
【发布时间】:2018-03-04 20:26:31
【问题描述】:
我有这段代码,但不明白为什么输出是 22!恐怕应该是01!
谁能解释会发生什么?如果列表存储了一个带参数的方法,那么参数应该分别为0和1!
List<Action> list = new List<Action>();
for (int i = 0; i < 2; i++)
{
list.Add(() => Console.Write(i));
}
foreach (var it in list)
{
it();
}
【问题讨论】:
标签:
c#
list
lambda
output
【解决方案1】:
它是闭包(1,2)。
在您的情况下,Console.Write(i) 将在动作调用时刻使用 i 的值。您首先在for 循环中增加i,然后在第二个循环中调用列表中的每个操作。在每个动作的调用时刻 i 的值为 2 - 因此,您将得到 22 作为输出。
要获得预期结果,您应该创建 i 的本地副本并使用它:
for (int i = 0; i < 2; i++)
{
var temp = i;
list.Add(() => Console.Write(temp));
}
【解决方案2】:
除了 Roma Doskoch 的 anwser,另一种方法是避免 for。
var list = Enumerable
.Range(0, 2)
.Select<int, Action>(i => () => Console.Write(i));
【解决方案3】:
闭包捕获变量,而不是值。
在您的代码中,闭包捕获变量i,而不是每次迭代时恰好存储在i 中的任何值。当您调用该操作时,变量i 的值为2(因为循环已完成),因此2 将被打印两次。
为了避免这种情况,正如其他答案已经指出的那样,您需要每次都创建一个新变量作为无法捕获值的解决方法;如果您在每次迭代中声明一个新变量,那么捕获该变量的结果等同于捕获该值,因为您不会在下一次迭代中更改它。