简体   繁体   中英

What is loop variable closure?

I have read in this question that in C# 5.0 was introduced loop variable closure , and I have accessed the link in the question to find out what it means. Shame on me, I wasn't able to understand much of what is a loop variable closure, since the blog article explains much about what involves to generate a warning from section blocks where before wasn't any compilation warning generated, and the impact of code changes at a new version of programming language. Since what I understand, the loop closure is not the format of foreach, but are the variables involved in array. Is this right?

Take a simple foreach loop:

foreach(var i in Enumerable.Range(1,10))
{
    Console.WriteLine(i);
}

Before C# 5, there was just one variable i that was used for the entire run (every iteration) of the loop.

After the introduction of C# 5, this loop will now have 10 separate i variables... a different one for each iteration of the loop. These variables have shorter lifetimes and all have the same name, but they are still unique variables. 1

At first glance the difference may not seem to matter, but when you're working with a closure the older behavior could have unexpected results.

You can see the difference with this code sample:

var results = new List<Func<int>>();
foreach(var i in Enumerable.Range(1,10))
{
    results.Add(() => i);
}
foreach(var item in results)
{
    Console.WriteLine(item());
}

This code will compile and run from both VS 2010 and VS 2012 (and later), but will give different results depending on which you used.

A closure is what happens when the compiler "closes over" or "hoists" a variable out of it's normal scope region and extends it's lifetime. Whenever you're working with a lambda expression (indicated by the => operator), there's very often a closure involved as well. In my sample, the variable i is used in a closure to be available to the anonymous functions placed in the list.

It's important to understand the distinction between the variable and value. If you can run the code in VS2010, when there was only one variable, the distinction is very clear... the value in the variable from earlier iterations of the loop can continue to be modified by later iterations of the loop, before the function is called, and so the code would output all 10 s. VS2012 and later users separate variables, and so will output 1 through 10 in sequence.


1 Before anyone asks: there is no performance difference. The difference is a compiler abstraction detail that may affect performance, but usually not in any measurable way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM