Implementation of Lambdas in C#

What is the output of the following program?

int x = 1;
Action action = (() => { Console.WriteLine(x); });
x = 2;

The output is of course 2, because delegates capture references to outer variables.

I was curious how this was implemented in the compiler.

The compiler rewrites the code above to something like this:

Scope s = new Scope();
scope.x = 1;
scope.x = 2;

and defines the Scope class like this:

private sealed class Scope
    public int x;
    public Scope();

    public void Call()

As we would expect, the is no way to create a reference to eg. an int in IL, so this is solved naturally - the int is wrapped inside Scope class and all accesses are done through the wrapper. The wrapper also defines the Call method, which is exactly the body of the anonymous delegate.

Actually, the compiler generated name for our Scope class is <>__DisplayClass1, and the Call method is named <Main>b__0.

For a little more complex example, see this post on StackOverflow.

© Martin Konicek 2022