如何升级到 C# 5.0?访问修改后的闭包

Posted

技术标签:

【中文标题】如何升级到 C# 5.0?访问修改后的闭包【英文标题】:how to upgrade to C# 5.0? access to modified closure 【发布时间】:2014-11-19 21:07:47 【问题描述】:

我觉得问这个有点傻。请不要打我太重。

最近我一直在使用 .Net framework 4.5 和 Visual C# 2012 以及 C# 5.0 之前的编译器;和 Visual Studio 2012。

我开始使用 Tasks,对来自 Resharper 的“访问修改后的关闭”通知感到恼火。然后我读到,如果我升级到 .Net 框架 4.5.2 并升级到后 C# 5.0,它会“修复”forforeach,这样我就不必在 curly 中创建临时变量由于共享上下文,循环的括号。

所以我觉得很好,这将是一个简单的修复。我做了以下事情:

1) 检查我使用的是 Visual Studio 2012,并且它与新的 4.5.2 框架和 C# 5.0 (here) 兼容

2) 然后我下载并安装了开发者版本的 .Net 4.5.2 (here)

3) 然后,我将解决方案中的每个项目定位为使用 .Net 4.5.2 而不是 .Net 4.5。我重建,运行了我的单元测试,并获得了所有的绿灯。

4) 然后我转到任务代码,并尝试删除临时变量。瞧,它仍然警告我访问修改后的闭包;例如:

    int numTasks = 1000;

    var tasks = new Task<int>[numTasks];

    for (int i = 0; i < numTasks; i++)
        tasks[i] = Task.Delay(1).ContinueWith(a => i); // <-- warning

上面的代码,因为共享上下文,会产生错误的输出。对于 .Net 4.5 和 C# 5.0 之前的版本,解决此问题的方法是引入一个临时变量,如下所示:

    int numTasks = 1000;

    var tasks = new Task<int>[numTasks];

    for (int i = 0; i < numTasks; i++)
    
        int i1 = i;
        tasks[i] = Task.Delay(1).ContinueWith(a => i1); <-- no warning, works great
    

我当然不喜欢这个,因为它很丑,必须评论让我的同事理解。我更愿意使用新版本的 C# 和 .Net 框架。

接下来我想,“如何检查我是否安装了 Visual Studio 2012 并使用了 C# 5.0?”这就是我卡住的地方。我的 Visual Studio 2012 环境似乎仍在使用 C# 4.5。我证明了这一点,即在执行我上面列出的升级步骤后,访问修改后的关闭问题没有解决。

有人可以帮助我了解如何摆脱 ****access to modified closure**** 问题,希望通过升级到 C# 5.0(如果这确实是我的问题)。

谢谢

【问题讨论】:

我远不是这方面的专家,但我认为这是与编译器/Visual Studio 相关的变化。你可能不是你可以随便加入的东西,你必须使用 VS 2013 嗯,如果正确的代码让他们感到不安,你需要新的同事。 C# v5 仅针对 foreach 修复它,而不针对 for。 【参考方案1】:

警告是完全正确的。您正在关闭稍后修改的变量。您提供的示例代码在 C# 4.0 和 C# 5.0(或 C# 3.0 或 C# 6.0)中的行为没有什么不同。

在 C# 5.0 中只有 foreach 循环被更改,以便在每次迭代时重新创建循环变量。 for 循环没有改变,闭包的语义也没有改变。

【讨论】:

Eric Lippert 有一篇很棒的博文,名为 Closing over the loop variable considered harmful。 当然...我应该更仔细地阅读。感谢大家的快速解答。

以上是关于如何升级到 C# 5.0?访问修改后的闭包的主要内容,如果未能解决你的问题,请参考以下文章

访问修改后的闭包 (2)

访问修改后的闭包 - 为啥这是一个建议的修复?

访问修改后的闭包:ReSharper

Do.. While.. 使用 Exists 谓词。访问修改后的闭包?

从 3.1 升级后的 .NET Core 5.0 Azure 部署 CORS 问题

关于 C# 闭包