Consider the following code:
class Program
{
static void Main(string[] args)
{
Func<uint> fibN = () => Fibonacci(n);
}
static uint Fibonacci(uint n)
{
return n <= 1 ? n : Fibonacci(n - 1) + Fibonacci(n - 2);
}
}
It does not comile, as soon as there is no variable n of a suitable type to be used. However if you add:
uint n = 5;
into Main method or
static uint n = 5;
to the class, the code will compile.
Let's disassemble. For the following code:
static void Main(string[] args)
{
uint n = 3;
Func<uint> fibN = () => Fibonacci(n);
}
we get:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 3
.locals init ([0] class [mscorlib]System.Func`1<uint32> fibN,
[1] class Utils.Program/'<>c__DisplayClass1' 'CS$<>8__locals2')
IL_0000: newobj instance void Utils.Program/'<>c__DisplayClass1'::.ctor()
IL_0005: stloc.1
IL_0006: nop
IL_0007: ldloc.1
IL_0008: ldc.i4.3
IL_0009: stfld uint32 Utils.Program/'<>c__DisplayClass1'::n
IL_000e: ldloc.1
IL_000f: ldftn instance uint32 Utils.Program/'<>c__DisplayClass1'::'<Main>b__0'()
IL_0015: newobj instance void class [mscorlib]System.Func`1<uint32>::.ctor(object,
native int)
IL_001a: stloc.0
IL_001b: nop
IL_001c: ret
} // end of method Program::Main
In this code you may find a hidden class c__DisplayClass1, in which we can see a public field of type uint32 named n:
.field public uint32 n
and method <Main>b__0:
.method public hidebysig instance uint32
'<Main>b__0'() cil managed
{
.maxstack 1
.locals init ([0] uint32 CS$1$0000)
IL_0000: ldarg.0
IL_0001: ldfld uint32 Utils.Program/'<>c__DisplayClass1'::n
IL_0006: call uint32 Utils.Program::Fibonacci(uint32)
IL_000b: stloc.0
IL_000c: br.s IL_000e
IL_000e: ldloc.0
IL_000f: ret
} // end of method '<>c__DisplayClass1'::'<Main>b__0'
which actually calls Fibonacci and passes the n variable. So the compiler extracted the local variable n into a separate class; as well as extracted lambda into a method of this class. In the end it looks like you assign c__DisplayClass1.<Main>b__0 to Func<uint> fibN.
naccessible in the scope, where the declaration offibNis placed