English 中文(简体)
How|Where are closed-over variables stored?
原标题:

This is a question based on the article "Closing over the loop variable considered harmful" by Eric Lippert.
It is a good read, Eric explains why after this piece of code all funcs will return the last value in v:

 var funcs = new List<Func<int>>();
 foreach (var v in values)
 {
    funcs.Add(() => v);
 }

And the correct version looks like:

 foreach (var v in values)
 {
    int v2 = v;
    funcs.Add(() => v2);
 }

Now my question is how and where are those captured v2 variables stored. In my understanding of the stack, all those v2 variables would occupy the same piece of memory.

My first thought was boxing, each func member keeping a reference to a boxed v2. But that would not explain the first case.

最佳回答

Ordinarily the variable v2 would be allocated some space on the stack at the start of the code block its found in. At the end of the code block (i.e. the end of the iteration) the stack is wound back (I m describing the logical scenario not an optimised actual behaviour). Hence each v2 is in effect a different v2 from the previous iteration although its true that it would end up occupying the same memory location.

However the compiler spots that v2 is being used by an anonymous function created by the lambda. What the compiler does is hoist the v2 variable. The compiler creates a new class that has an Int32 field to hold the value of v2, it is not allocated a place on the stack. It also makes the anonymous function a method of this new type. (For simplicity I ll give this un-named class a name, lets call it "Thing").

Now in each iteration a new instance of "Thing" is created and when v2 is assigned its the Int32 field which is actually assigned not just a point in stack memory. The anonymous function expression (the lambda) will now return a delegate which has non-null instance object reference, this reference will be to the current instance of "Thing".

When the delegate for anonymous function is invoked it will execute as an instance method of a "Thing" instance. Hence v2 is available as a member field and will have the value give it during the iteration this instance of "Thing" was created.

问题回答

Further to the answers from Neil and Anthony, here s an example of the code that might be auto-generated in both cases.

(Note that this is only to demonstrate the principle, the actual compiler-generated code won t look exactly like this. If you want to see the real code then you can take a look using Reflector.)

// first loop
var captures = new Captures();
foreach (var v in values)
{
    captures.Value = v;
    funcs.Add(captures.Function);
}

// second loop
foreach (var v in values)
{
    var captures = new Captures();
    captures.Value = v;
    funcs.Add(captures.Function);
}

// ...

private class Captures
{
    public int Value;

    public int Function()
    {
        return Value;
    }
}




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签