3

To illustrate my confusion, see the following example:

int a = 0;
Action act = () => ++a;
act();
Console.WriteLine(a);

I have difficulty figuring out how modification to the captured variable within the lambda could possibly affect the local variable a. First of all, the implicitly generated lambda function object could not store a reference to the local variable a. Otherwise, if act is returned and invoked later, the referenced local variable a would already be vanished. A solution to this problem would be copy-by-value, either by copying the int value directly or through boxing, so that the function object would have its own copy the local variable a. But this doesn't explain the example just given. So, what is the underlying mechanism? Would it be that the seemingly local variable a is actually no longer a local variable, but translated by the compiler to be a reference to an int field within the generated lambda function object?

Lingxi
  • 14,579
  • 2
  • 37
  • 93
  • 4
    An inner class in created: http://tryroslyn.azurewebsites.net/#f:r/K4Zwlgdg5gBAygTxAFwKYFsDcAoADsAIwBswBjGUogQxBBgGEYBvbGNmfYsmANwHswAExgBZABQBKZq3azsASHmRkMKjAC8MAAw5FAQVLIwfCKsMaYkjQD4YAajtVd8qocnP6JkHyKoAdADqAE5gaAAykKhiVBKYsnLx7DJsAL7YKUAA – Dennis_E Apr 12 '16 at 08:32
  • 1
    `but translated by the compiler to be a reference to an int field within the generated lambda function object?` Spot-on guess :) – Rob Apr 12 '16 at 08:33
  • @Dennis_E I know that. The real question is: is `a` at the first line a local variable of type `int` or just a reference into an `int` field of the generated lambda function object which is an instance of the inner class? – Lingxi Apr 12 '16 at 08:34
  • 1
    @Lingxi Check out the converted code. It moves `a` into a new class, and when you write `Console.WriteLine(a)`, it converts it to use the lambda-object's `a` instead. – Rob Apr 12 '16 at 08:36
  • In C++ you have to explicitly reference all variables you want to use, in C# it (a) is automatically in scope. – Mafii Apr 12 '16 at 08:36
  • 1
    Your last sentence says it: `a` is no longer a local variable, but a field of this new inner class. – Dennis_E Apr 12 '16 at 08:37
  • @Dennis_E, exactly – Mafii Apr 12 '16 at 08:39
  • @Rob With a C++ background, I'm really surprised by the way C# implements lambda capture. – Lingxi Apr 12 '16 at 08:47
  • They had their reasons for doing it this way. I remember an article about this, but of course I can't find it. – Dennis_E Apr 12 '16 at 08:58

1 Answers1

2

The point here is closure. After compilation a is not a local variable anymore - it's a field of auto-generated class, both in function scope and in lambda.

Community
  • 1
  • 1
Andrey Ershov
  • 1,773
  • 1
  • 16
  • 26