简体   繁体   English

什么是循环变量关闭?

[英]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. 我已经阅读了这个问题 ,在C#5.0中引入了循环变量闭包 ,并且已经访问了问题中的链接以了解它的含义。 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. 据我了解,循环闭包不是foreach的格式,而是数组中涉及的变量。 Is this right? 这是正确的吗?

Take a simple foreach loop: 进行一个简单的foreach循环:

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. C#5 之前 ,只有一个变量i用于循环的整个运行(每次迭代)。

After the introduction of C# 5, this loop will now have 10 separate i variables... a different one for each iteration of the loop. 引入C#5之后,此循环现在将具有10个独立的i变量...循环的每次迭代都有一个不同的变量。 These variables have shorter lifetimes and all have the same name, but they are still unique variables. 这些变量的生存期较短,并且都具有相同的名称,但是它们仍然是唯一变量。 1 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. 该代码将在VS 2010和VS 2012(及更高版本)中编译并运行,但是根据您使用的代码,将给出不同的结果。

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. 一个closure是当编译器“关闭了”或“笼”变出来的是正常范围区域,延长它的寿命会发生什么。 Whenever you're working with a lambda expression (indicated by the => operator), there's very often a closure involved as well. 每当使用lambda表达式(由=>运算符表示)时,通常也会涉及到闭包。 In my sample, the variable i is used in a closure to be available to the anonymous functions placed in the list. 在我的示例中,变量i在闭包中使用,可用于列表中的匿名函数。

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. 如果您可以在VS2010中运行代码,那么在只有一个变量的情况下,区别就很明显了……循环的早期迭代中的变量值可以继续被循环的后续迭代修改,然后再执行功能被调用,因此代码将输出所有10 s。 VS2012 and later users separate variables, and so will output 1 through 10 in sequence. VS2012和更高版本的用户将变量分开,因此将按顺序输出110


1 Before anyone asks: there is no performance difference. 1在有人问之前:没有性能差异。 The difference is a compiler abstraction detail that may affect performance, but usually not in any measurable way. 区别在于编译器抽象细节可能会影响性能,但通常不会以任何可衡量的方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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