将值类型捕获到lambda时是否执行复制?

Ste*_*nov 8 .net c# struct value-type

struct SomeStruct
{
    public int Num { get; set; }
}

class Program
{
    static Action action;

    static void Foo()
    {
        SomeStruct someStruct = new SomeStruct { Num = 5 };
        action = () => Console.WriteLine(someStruct.Num);
    }

    static void Main()
    {
        Foo();
        action.Invoke();
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 是否在创建lambda时创建了someStruct的副本?
  2. 是Foo返回时创建的someStruct的副本?
  3. 我可以验证没有发生复制吗?在C++中,我将实现复制构造函数并从其中进行打印.

该标准的引文将不胜感激.任何相关的在线文章也是如此.

Dan*_*iel 9

没有副本.Lambdas捕获变量,而不是值.

您可以使用Reflector查看编译代码:编译器将"someStruct"变量移动到辅助类中.

private static void Foo()
{
    DisplayClass locals = new DisplayClass();
    locals.someStruct = new SomeStruct { Num = 5 };
    action = new Action(locals.b__1);
}
private sealed class DisplayClass
{
    // Fields
    public SomeStruct someStruct;

    // Methods
    public void b__1()
    {
        Console.WriteLine(this.someStruct.Num);
    }
}
Run Code Online (Sandbox Code Playgroud)

复制结构永远不会导致用户定义的代码运行,因此您无法真正检查它.实际上,代码将在分配给"someStruct"变量时进行复制.即使对于没有任何lambdas的局部变量,它也会这样做.


alb*_*ein 6

它不会被复制,它会创建一个闭包.基本上它会将结构封装在一个对象中,而不是在堆栈上创建它.

如果你想确保你总是可以使用反射器,但是没有必要,这个行为在Raymond Chen博客上有解释.