When I capture an int
in a lambda, I guess it's allocated in the heap, to prevent deallocation at the end of the block.
Then, how/when is it deallocated? Is the value boxed (then it must work like any other reference)? Is there a special functionality in the GC to manage structs on the heap?

- 1,257
- 11
- 25
-
1Your captured variable becomes a field of a hidden class. The class object behaves like any other. Use ildasm.exe to see that for yourself. – Hans Passant Mar 09 '16 at 12:31
1 Answers
When a local variable is captured in the lambda, it becomes a regular field in the compiler-generated lambda class. For example, this:
static void Main(string[] args) {
int capture = 5;
Func<int, int> func = input => input * capture;
}
Can be lowered by a C# compiler to this:
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public int capture;
internal int <Main>b__0(int input)
{
return input * this.capture;
}
}
private static void Main(string[] args)
{
new C.<>c__DisplayClass0_0().capture = 5;
}
Thus:
Then, how/when is it deallocated?
It is deallocated just like a regular value type field of a class instance, when the class instance is deallocated.
Is the value boxed (then it must work like any other reference)?
In general, we use boxing to refer to the implicit representation-changing conversion of a value type to a special reference type whose only function is to (later) enable non-representation changing assignments of the original value to reference type locations (typically of type object
or any interface type that the original value type implemented). Under the hood, boxing is performed by the CLR using a special IL instruction.
In the context of lambdas, even though the value probably goes to the heap as a field of a class instance, we don't call it boxing in the regular sense. Under the hood, capturing a variable is something that the C# compiler takes care of, by writing some equivalent boilerplate code for you.
Of course, as pointed out in the comments, in the end they both boil down to the same thing: they allocate a struct on the heap.
Is there a special functionality in the GC to manage structs on the heap?
Nothing special is required for lambda captures specifically. The GC already knows how to deallocate value type fields.

- 1
- 1

- 28,773
- 8
- 68
- 104
-
@HenkHolterman ???? Only in the most general way... Instead of an value type now you have a reference type containing the value type... But if you have multiple value types, the hidden reference type is still one. – xanatos Mar 09 '16 at 12:47
-
2@HenkHolterman I don't disagree with you - in fact, it crossed my mind while writing this answer. But I prefer to avoid redefining well-understood terms of a particular technology. In C#, they use "boxing" to mean the automated wrapping of a value type to a *dedicated* reference type that implements the value type's interfaces - they don't (traditionally) use "boxed struct" to refer *any* heap-allocated struct. – Theodoros Chatzigiannakis Mar 09 '16 at 12:55
-
-
@HenkHolterman and Theodoros Chatzigiannakis thanks for your comments. I would have asked how it was different from boxing. Now I know. – krimog Mar 09 '16 at 13:06