开发者

Is copying performed when capturing a value-type into a lambda?

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();
    }
}
  1. Is a copy of someStruct created when the lambda is created?
  2. Is a copy of someStruct created when Foo returns?
  3. Can I verify that copying doesn't occur? In C++ I'd implement the copy constructor and print from inside it.

Citations from the standard will开发者_JAVA技巧 be appreciated. Any relevant online articles as well.


There will be no copies. Lambdas capture variables, not values.

You can use Reflector to look at the compile code: the compiler will move the "someStruct" variable into a helper class.

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

Copying structures will never cause user-defined code to run, so you cannot really check it that way. Actually, the code will do a copy when assigning to the "someStruct" variable. It would do that even for local variables without any lambdas.


It won't be copied, it creates a closure. Basically it'll encapsulate the structure in one object instead of creating it on the stack.

If you want to be sure you can always use reflector, but there is no need for that, the behavior is explained on Raymond Chen blog.


See The implementation of anonymous methods in C# and its consequences (part 1). Your code is actually something like:

   class SomeHiddenClass {
     SomeStruct someStruct;
     someHiddenMethod() {
       Console.WriteLine(someStruct.Num);
     }
   }

   SomeHiddenClass someHiddenVar = new SomeHiddenClass();
   someHiddenVar.someStruct.Num = 5;
   action = someHiddenVar.someHiddenMethod;


No, it doesn't copy, for the same reason (compiler creates a behind the scenes class to hold the value) that a copy of other value types isn't created when you capture a variable in a lambda.

for example, if you do:

int i = 7;
Action a = () => Console.WriteLine("lambda i=" + i);
i++;
a(); //prints 8
Console.WriteLine("main i=" + i); //prints 8

the lambda shares the 'i' with the declaring scope. same thing will happen with your struct. you can do this as a test to prove that copying doesn't occur.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜