Simple, not putting stack .
The delegate infrastructure which is the basic mechanism of lambda allows the use of what is called closure ). That is, it holds a state within the function and takes it with it wherever it goes. It is not that the data needs to become a reference, but it will need to have some reference to some object in the heap where it has the data.
Then the compiler generates an internal code that treats what would normally be in the stack and puts it in heap which is a place where the data has indefinite life time
In this case, the lifetime of this data, accessed by a variable, is linked to the lifetime of the anonymous function. In the case of .NET your destruction will occur sometime after a garbage collection is fired at the generation it is in.
So long as the lambda exists the variable will exist, it will not be freed.
Note that there may be some unexpected effect, especially in loops, since the local value may be decoupled from the lambda value. A common example is a loop going up to 10 and having lambda run later, even though the person does not realize what it is after, and the value will always be 10 instead of 1 to 10 as the person would expect. The lambda is a mechanism used for lazy evaluation .
How is it internally
I could not name anyone other than the guy who wrote the compiler code that does this, ladies and gentlemen : Eric Lippert .
class C1 {
Func<int, int, int> M() => (x, y) => x + y;
}
Turns into:
class C1 {
static Func<int, int, int> theFunction;
static int Anonymous(int x, int y) => x + y;
Func<int, int, int> M() {
if (C1.theFunction == null) C1.theFunction = C1.Anonymous;
return C1.theFunction;
}
}
Actual code in SharpLab .
class C2 {
static int counter = 0;
int x = counter++;
Func<int, int> M() => y => this.x + y;
}
Turns into:
class C2 {
static int counter = 0;
int x = counter++;
int Anonymous(int y) => this.x + y;
Func<int, int> M() => this.Anonymous;
}
real code in SharpLab .
class C3 {
static int counter = 0;
int x = counter++;
Func<int> M(int y) => () => x + y;
}
Turns into:
class C3 {
class Locals {
public C3 __this;
public int __y;
public int Anonymous() => this.__this.x + this.__y;
}
Func<int> M(int y) {
var locals = new Locals();
locals.__this = this;
locals.__y = y;
return locals.Anonymous;
}
}
real code in SharpLab .
If I fix the time I do the C4: P