如何告诉Lambda函数捕获副本而不是C#中的引用? [英] How to tell a lambda function to capture a copy instead of a reference in C#?

查看:83
本文介绍了如何告诉Lambda函数捕获副本而不是C#中的引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've been learning C#, and I'm trying to understand lambdas. In this sample below, it prints out 10 ten times.

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语法

Obviously, the generated class behind the lambda is storing a reference or pointer to the int i variable, and is assigning a new value to the same reference every time the loop iterates. Is there a way to force the lamda to grab a copy instead, like the C++0x syntax

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

vs.

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

推荐答案

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

What the compiler is doing is pulling your lambda and any variables captured by the lambda into a compiler generated nested class.

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

After compilation your example looks a lot like this:

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);
                }
        }
}

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

By making a copy within the for loop, the compiler generates new objects in each iteration, like so:

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

这篇关于如何告诉Lambda函数捕获副本而不是C#中的引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆