Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 be appreciated. Any relevant online articles as well.

like image 217
Stefan Monov Avatar asked Dec 30 '09 19:12

Stefan Monov


2 Answers

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.

like image 55
Daniel Avatar answered Oct 26 '22 13:10

Daniel


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.

like image 21
albertein Avatar answered Oct 26 '22 13:10

albertein