一尘不染

如何告诉Lambda函数捕获副本而不是C#中的引用?

c#

我一直在学习C#,并且试图理解lambda。在下面的此示例中,它打印出10十次。

class Program
{
    delegate void Action();
    static void Main(string[] args)
    {
        List<Action> actions = new List<Action>();

        for (int i = 0; i < 10; ++i )
            actions.Add(()=>Console.WriteLine(i));

        foreach (Action a in actions)
            a();
    }
}

显然,在lambda后面生成的类正在存储对该int i变量的引用或指针,并在每次循环迭代时都将新值分配给相同的引用。有没有办法强迫lamda代替副本,例如C ++ 0x语法

[&](){ ... } // Capture by reference

[=](){ ... } // Capture copies

阅读 198

收藏
2020-05-19

共1个答案

一尘不染

编译器正在做的是将您的lambda和lambda捕获的任何变量拉入编译器生成的嵌套类。

编译后,您的示例如下所示:

class Program
{
        delegate void Action();
        static void Main(string[] args)
        {
                List<Action> actions = new List<Action>();

                DisplayClass1 displayClass1 = new DisplayClass1();
                for (displayClass1.i = 0; displayClass1.i < 10; ++displayClass1.i )
                        actions.Add(new Action(displayClass1.Lambda));

                foreach (Action a in actions)
                        a();
        }

        class DisplayClass1
        {
                int i;
                void Lambda()
                {
                        Console.WriteLine(i);
                }
        }
}

通过在for循环中进行复制,编译器将在每次迭代中生成新对象,如下所示:

for (int i = 0; i < 10; ++i)
{
    DisplayClass1 displayClass1 = new DisplayClass1();
    displayClass1.i = i;
    actions.Add(new Action(displayClass1.Lambda));
}
2020-05-19