什么是循环变量闭包?

时间:2016-06-21 20:34:49

标签: c# foreach closures

我已在this question中读到,在C#5.0中引入了loop variable closure,我已经访问了问题中的链接以找出它的含义。对我感到羞耻,我无法理解什么是循环变量闭包,因为博客文章解释了很多关于从块块生成警告的内容,其中之前没有生成任何编译警告,以及新版编程语言中代码更改的影响。根据我的理解,循环闭包不是foreach的格式,而是数组中涉及的变量。这是对的吗?

1 个答案:

答案 0 :(得分:3)

采用简单的foreach循环:

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

C#5之前,只有一个变量i用于循环的整个运行(每次迭代)。

引入C#5之后,这个循环现在将有10个单独的i变量......每个循环迭代都有一个不同的变量。这些变量的生命周期较短,并且都具有相同的名称,但它们仍然是唯一的变量。 1

乍一看,差异似乎并不重要,但是当您使用关闭时,较旧的行为可能会产生意外结果。

您可以看到与此代码示例的区别:

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());
}

此代码将从VS 2010和VS 2012(及更高版本)编译和运行,但会根据您使用的结果给出不同的结果。

编译器&#34;关闭时会发生closure&#34;或者&#34;升降机&#34;一个变量超出它的正常范围区域并延长它的寿命。每当您使用lambda表达式(由=>运算符指示)时,通常也会涉及闭包。在我的示例中,变量i在闭包中用于放置在列表中的匿名函数。

了解变量和值之间的区别非常重要。如果你可以在VS2010中运行代码,当只有一个变量时,区​​别非常清楚......循环的早期迭代中变量中的值可以继续被循环的后续迭代修改,在函数之前被调用,因此代码将输出所有10 s。 VS2012及以后的用户将变量分开,因此将依次输出110

1 在有人要求之前:没有性能差异。区别在于可能影响性能的编译器抽象细节,但通常不会以任何可测量的方式。