【问题标题】: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】:

它是闭包(12)。

在您的情况下,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 将被打印两次。

      为了避免这种情况,正如其他答案已经指出的那样,您需要每次都创建一个新变量作为无法捕获值的解决方法;如果您在每次迭代中声明一个新变量,那么捕获该变量的结果等同于捕获该值,因为您不会在下一次迭代中更改它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多