I've seen countless posts on how variable capture pulls in variables for the creation of the closure, however they all seem to stop short of specific details and call the whole thing "compiler magic".
I'm looking for a clear-cut explanation of:
- How local variables are actually captured.
- The difference (if any) between capturing value types vs. reference types.
- And whether there is any boxing occurring with respect to value types.
My preference would be for an answer in terms of values and pointers (closer to the heart of what happens internally), though I will accept a clear answer involving values and references as well.
It's probably easiest to demonstrate how the capturing works via an example...
Here's some code using a lambda expression which captures a single variable:
Now here's what the compiler's doing for you - except that it would use "unspeakable" names which couldn't really occur in C#.
If you capture variables declared in a loop, you'd end up with a new instance of
ActionHelper
for each iteration of the loop - so you'd effectively capture different "instances" of the variables.It gets more complicated when you capture variables from different scopes... let me know if you really want that sort of level of detail, or you could just write some code, decompile it in Reflector and follow it through :)
Note how:
EDIT: Here's an example of two delegates sharing a variable. One delegate shows the current value of
counter
, the other increments it:... and the expansion: