【问题标题】:Has foreach's use of variables been changed in C# 5?在 C# 5 中是否更改了 foreach 对变量的使用?
【发布时间】:2012-08-20 05:21:41
【问题描述】:

在https://stackoverflow.com/a/8649429/1497 Eric Lippert 的这个答案中,关于 foreach 循环如何使用该变量,“仅供参考,我们很可能会在下一个 C# 版本中解决此问题;这是开发人员的主要痛点”。

在下一个版本中,每次运行“foreach”循环时,我们都会生成一个新的循环变量,而不是每次都关闭同一个变量。这是一个“重大”更改,但在绝大多数情况下,“中断”将修复而不是导致错误。

我还没有找到任何表明此更改已完成的信息。是否有任何迹象表明这就是 foreach 循环在 C# 5 中的工作方式?

【问题讨论】:

  • 所引用的foreach 是 C# 语言功能,而不是 .NET Framework 功能。
  • 感谢@BoltClock。我已将问题更新为针对 C# 5。不过,为了澄清起见,如果我在 VS 2012 中针对 .Net 4.5 构建 C# 项目,我是否可能使用 C# 5?
  • @a_hardin:除非您要求它使用不同的编译器,否则无论目标框架如何,您都将对 VS2012 中的任何项目使用 C#5.0。要将编译器更改为特定版本,请转到项目属性,构建选项卡,然后单击右下角的高级...。然后更改“语言版本”下拉菜单。
  • @JeffYates 我尝试在 VS2012 中更改语言版本,但它始终遵循“新”约定(即 foreach 变量是“内部”变量,并且捕获了不同的“副本”在每次迭代中)。您是否真的验证过更改语言版本对您有效? (这主要是理论上的兴趣;我认为没有人会希望在实践中使用 C# 4 行为)。
  • @JeppeStigNielsen:很有趣。我没试过。也许它只会尊重语法差异而不是规范更改。这很令人惊讶。有机会我一定要看看。你是如何验证的? IL 或应用行为?

标签: c# foreach .net-4.5 c#-5.0


【解决方案1】:

这是对 C# 语言的更改,而不是对 .NET 框架的更改。因此,它只影响在 C# 5.0 下编译的代码,而不管该代码将在哪个 .NET 框架版本上执行。

C# 5.0

规范的第 8.8.4 节明确表示已经进行了此更改。具体来说,C# 5.0 规范的第 249 页指出:

foreach (V v in x) embedded-statement

然后扩展为:

{
    E e = ((C)(x)).GetEnumerator();
    try {
        while (e.MoveNext()) {
            V v = (V)(T)e.Current;
            embedded-statement
        }
    }
    finally {
        … // Dispose e
    }
}

后来:

在while循环中v的位置对于它的方式很重要 由发生在 嵌入语句。

C# 4.0

与 C# 4.0 规范相比,该规范的更改很明显(再次在第 8.8.4 节中,但这次是第 247 页):

foreach (V v in x) embedded-statement

然后扩展为:

{
    E e = ((C)(x)).GetEnumerator();
    try {
        V v;
        while (e.MoveNext()) {
            v = (V)(T)e.Current;
            embedded-statement
        }
    }
    finally {
        … // Dispose e
    }
}

请注意,变量v 是在循环外而不是在循环内声明的,就像在 C# 5.0 中一样。

注意

您可以在VC#\Specifications\1033 下的Visual Studio 安装文件夹中找到C# 规范。 VS2005、VS2008、VS2010 和 VS2012 就是这种情况,让您可以访问 C# 1.2、2.0、3.0、4.0 和 5.0 的规范。您也可以在 MSDN 上搜索C# Specification 找到规范。

【讨论】:

  • 举个例子就好了:List<Action> list = new List<Action>(); foreach (var i in new int[] { 1, 2, 3, 4, 5 }) { list.Add(() => Console.WriteLine(i)); } foreach (var f in list) { f(); }
  • 我不确定这里是否需要一个示例,因为 OP 已经了解正在讨论的问题并且只是在寻找对更改的确认。
  • 也就是说,感谢您发布一个。对于需要上下文的这个问题的未来观众,我可以看到它的价值。也许可以以某种方式对其进行编辑而不会混淆事物。谢谢。
  • 这是否会影响性能,因为每次迭代都必须创建一个新变量?
  • @colinfang:根据 Eric Lippert 的评论,C#4 之前的规范是错误的 (stackoverflow.com/questions/8649337/…)
猜你喜欢
  • 2016-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-13
  • 2015-05-25
相关资源
最近更新 更多