代码之家  ›  专栏  ›  技术社区  ›  Jader Dias

为什么在这种情况下,事件的行为会有所不同?

  •  0
  • Jader Dias  · 技术社区  · 14 年前

    以下程序

    static IEnumerable<Action> Create()
    {
        foreach (var i in Enumerable.Range(0, 2))
        {
            yield return () => { Console.Write(i); };
        }
    }
    
    static void Main(string[] args)
    {
        foreach (var func in Create())
        {
            func();
        }
    
        Console.ReadLine();
    }
    

    输出

    01年

    还有这个节目

    static event Action SomethingHappened;
    
    static void Register()
    {
        foreach (var i in Enumerable.Range(0, 2))
        {
            SomethingHappened += () => { Console.Write(i); };
        }
    }
    
    static void Main(string[] args)
    {
        Register();
        SomethingHappened();
        Console.ReadLine();
    }
    

    输出

    十一

    为什么会这样?如何使程序2输出 01 ?

    2 回复  |  直到 14 年前
        1
  •  3
  •   Jon Skeet    14 年前

    在lambda表达式中捕获循环变量。这意味着当委托最终被调用时,它将使用变量的最新值。。。永远是1。试试这个:

    foreach (var i in Enumerable.Range(0, 2))
    {
        int copy = i;
        SomethingHappened += () => { Console.Write(copy); };
    }
    

    ... 然后读 Eric Lippert's blog post 关于它。

        2
  •  1
  •   Brian Rasmussen    14 年前

    在第二个程序中,变量 i 被羔羊抓住了。要获得正确的行为,请在lambda中使用本地副本。例如。

    foreach (var i in Enumerable.Range(0, 2))
    {
        var local = i;
        SomethingHappened += () => { Console.Write(local); };
    }