A quick note on Closing lambda loop variables in C# 5.0 - Breaking Changes in C# 5.0 compiler


ANOOP MADHUSUDANAN

Vote on HN

This pimageost is regarding a breaking change in C# 5.0 related to using variables in lambdas with in a loop.

For example, prior to C# 5.0 compiler, the following code

        
     //** Code Example 1 **
 
     static void Main(string[] args)
        {
            var items = new List<int>() { 1, 2, 3, 4, 5 };
            var queue = new List<Func<int>>();
            foreach (var item in items)
                queue.Add(() => item);
            foreach (var q in queue) Console.WriteLine(q());
            Console.Read();
        
    }
will produce the following output

image

This is because prior the C# 5.0, the compiler closes/captures the reference of the lambda/loop variable than its actual value. And hence the value defaults to the current value at the time of invocation (here, when invoking the q() method) instead of the value at the time of using the variable in the expression (when adding it to the queue). So, earlier, the compiler forced you to declare a local variable in a loop (counter intuitive any day)   because if you want to see the expected output, you need to manually close the variable by assigning it to some other variable, like

    //** Code Example 2 **

   static void Main(string[] args)
        {
            var items = new List<int>() {1,2,3,4,5};
            var queue = new List<Func<int>>();
            foreach (var item in items)
            {
                //Prior to C# 5.0 this was required to correctly
                //capture the value
                var val = item;
                queue.Add(() => val);
            }
            foreach (var q in queue) Console.WriteLine(q());
            Console.Read();
        }
    }

And this should give the output as below.

image

From C# 5.0 onwards, the compiler will capture the value of the variable instead of it’s reference when you use a variable in a lambda expression with in a loop. So, Code Example 1 will provide Output Listing 2 that eliminates the need to capture the value manually, and you can write better code with out being forced to have local variables with in a loop.

© 2012. All Rights Reserved. Amazedsaint.com