Interesting (good) Behavior of Closures

For some reason, I didn’t think this would work, but it does:

            Customer c = null;
            Func<string> func = ()=>c.LookupName;
            c = new Customer {LookupName = "First"};
            System.Diagnostics.Debug.WriteLine(func());

I would’ve expected an NRE in the WriteLine because the ‘c’ reference (null) would’ve been packaged up by the closure.  But apparently it packages up the reference to the reference also so that if the ‘c’ variable value changes, so does the closure’s reference to it. 

The output is not an NRE, but rather “First”.

I was curious what it would do with valid references. Consider the following example:

            Customer c = new Customer{LookupName="First"};
            Func<string> func = ()=>c.LookupName;
            c = new Customer {LookupName = "Second"};
            System.Diagnostics.Debug.WriteLine(func());

The output is, as you would expect, “Second”.

One last stretch here, what about stack-based value types:

            int i = -1;
            Func<int> func = ()=>i;
            i = 99;
            System.Diagnostics.Debug.WriteLine(func());

The output is 99.

The way it works under the hood is that the compiler doesn’t actually create a new stack variable called ‘i’ (like it would normally), it creates a new class called <>c__DisplayClass2d in my case. Well, that’s hard to type, so let’s just call it FancyClass:

            public class FancyClass{
                public int i;

                public int GetI(){
                    return i;
                }
            }

Then, it re-writes — rather it compiles slightly different IL — the code above (the int i = -1 example) like this:

            FancyClass c = new FancyClass();
            c.i = -1;
            Func<int> func = ()=>c.i;
            c.i = 99;
            System.Diagnostics.Debug.WriteLine(func());

Seen like this, it seems a bit more obvious.

Many of you are probably saying “Duh!”, but this went against my understanding of how closures package up their context. 

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Chad Myers

Chad Myers is the Director of Development for Dovetail Software, in Austin, TX, where he leads a premiere software team building complex enterprise software products. Chad is a .NET software developer specializing in enterprise software designs and architectures. He has over 12 years of software development experience and a proven track record of Agile, test-driven project leadership using both Microsoft and open source tools. He is a community leader who speaks at the Austin .NET User's Group, the ADNUG Code Camp, and participates in various development communities and open source projects.
This entry was posted in .NET, Misc. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://jdscolam.blogspot.com Jon Scolamiero

    I like this behavior as it lets us do some setup early on in a method without worrying that the variable my not be instantiated yet.

  • http://dotnetslackers.com/community/blogs/simoneb Simone Busoli

    Hi Chad, yeah, that’s a cool behavior, and has somewhat become intuitive, since as lambda – or an anonymous method – are pointers to methods, not actually code which gets executed, therefore they create a closure around the variables of the environment and actually use them only when they are invoked.

    That’s why, when you create loops which call anonymous methods, at times you need to declare an inner variable which disconnects from the outer closure and keeps the right value of the variable for each iterations, and the following example usually doesn’t work as expected:

    var handle = new ManualResetEvent(false);

    for(int i = 0; i < 1000000; i++)
    ThreadPool.QueueUserWorkItem(() =>
    {
    handle.WaitOne();
    Console.WriteLine(i);
    });

    handle.Set();

    PS. Wrote it without the compiler, I’m not sure it does, but you get the idea.