using loop variables in lambda expressions in c# 5.0

In this post i will write about a problem you can get in if you use a loop variable in a lambda expression or anonymous method. If you use an external variable within a lamabda expression the c# compiler generates a closure that includes the external variable and so the lambda can use the value of this variable. That normaly works good but if you use a loop variable within the a lambda and compile it with a c# 4.0 compiler you get a worng result. In the following code segment i build ten lambdas including the loop variable. That means a closure is build for every lambda. I save the lambdas to the list and when the loop ends i execute the ten lambdas.

var enumerable = Enumerable.Range(1, 10);
List<Action> list = new List<Action>();
foreach (var item in enumerable)
{
    Action lambda = () =>
    {
        var result = 2 * item;
        Trace.WriteLine(result);
    };
    list.Add(lambda);
}
foreach(var listitem in list)
{
    listitem();
}

After executing the lambdas the output is the following:

If i compile the same code with the c# 5 compiler and execute it i get the correct result:

As you see the c# 5 compiler builds the closures correct with the correct loop variables. If we want to get the correct value with the c# 4 compiler we must use a local variable. In the following code segment the loop value is assigned to a local variable. Now the compiler builds the correct closure.

var enumerable = Enumerable.Range(1, 10);
List<Action> list = new List<Action>();
foreach (var item in enumerable)
{
    // assigning local variable
    var localItem = item;
    Action lambda = () =>
    {
        // using local variable
        var result = 2 * localItem;
        Trace.WriteLine(result);
    };
    list.Add(lambda);
}
foreach(var listitem in list)
{
    listitem();
}

This is the output of the corrected code segment:

So i am glad that Microsoft fixed this problem. It was easy to fix but i think now it works much more logical.

Advertisements