In C# 7.0 you can declare local functions, i.e. functions living inside another method. These local functions can access local variables of the surrounding method. Since the
This works because the compiler creates a delegate which captures the factor variable in a closure.
In fact if you use a decompiler, you'll see that the following code is generated:
public static Func AssignLocalFunctionToDelegate()
{
int factor = 3;
return delegate (int x) {
return (factor * x);
};
}
You can see that factor will be captured in a closure. (You are probably already aware that behind the scenes the compiler will generate a class that contains a field to hold factor.)
On my machine, it creates the following class to act as a closure:
[CompilerGenerated]
private sealed class <>c__DisplayClass1_0
{
// Fields
public int factor;
// Methods
internal int g__Triple0(int x)
{
return (this.factor * x);
}
}
If I change AssignLocalFunctionToDelegate() to
public static Func AssignLocalFunctionToDelegate()
{
int factor;
int Triple(int x) => factor * x;
factor = 3;
Console.WriteLine(Triple(2));
return Triple;
}
then the implementation becomes:
public static Func AssignLocalFunctionToDelegate()
{
<>c__DisplayClass1_0 CS$<>8__locals0;
int factor = 3;
Console.WriteLine(CS$<>8__locals0.g__Triple0(2));
return delegate (int x) {
return (factor * x);
};
}
You can see that it is creating an instance of the compiler-generated class for use with the Console.WriteLine().
What you can't see is where it actually assigns 3 to factor in the decompiled code. To see that, you have to look at the IL itself (this may be a failing in the decompiler I'm using, which is fairly old).
The IL looks like this:
L_0009: ldc.i4.3
L_000a: stfld int32 ConsoleApp3.Program/<>c__DisplayClass1_0::factor
That's loading a constant value of 3 and storing it in the factor field of the compiler-generated closure class.