c# – 重现“接近foreach的变量”

使用Visual Studio 2013,我试图重现Eric Lippert的博客文章 “Closing over the loop variable considered harmful”提到的getcha.

在项目属性中,我选择“C#3.0”作为语言版本(Build> Advanced …).此外,我选择了“.NET Framework 3.5”作为目标框架,好像我认为这不应该是必要的,因为这只是关于语言.

运行他的代码

using System;
using System.Collections.Generic;

namespace Project1
{
    class Class1
    {
        public static void Main(string[] args)
        {
            var values = new List<int>() { 100,110,120 };
            var funcs = new List<Func<int>>();
            foreach (var v in values)
            {
                funcs.Add(() => v);
            }
            foreach (var f in funcs)
                Console.WriteLine(f());
        }
    }
}

预期产量:

120
120
120

实际输出

100
110
120

正如“Is there a reason for C#’s reuse of the variable in a foreach?” 0700所示:

The for loop will not be changed,and the change will not be “back ported” to prevIoUs versions of C#. You should therefore continue to be careful when using this idiom.

我究竟做错了什么?

解决方法

斯科特的答案是正确的,但可以使用一些额外的澄清.

这里的问题是“语言版本”开关不能做你认为的.在我看来,这是一个非常错误的,因为它是非常误导的. “语言版本”开关并不意味着“使用旧的编译器”;它不是兼容模式.

相反,它意味着“使用当前的编译器,并且如果我使用在所选语言版本中不可用的功能,则会产生错误”.

这个切换的原因是,开发团队中的一个人可以“尝试”一个新版本的编译器,以确保他们的代码仍然有效,但是在他们检查之前知道他们没有意外地使用一个语言功能他们的队友的编辑者会窒息.所以如果你将语言版本设置为3.0,那么“动态”将不起作用(因为它被添加到C#4.0中),但它仍然是您安装的任何版本的编译器.

正如Scott指出的,如果你想使用旧的编译器,你必须在你的机器上实际找到一个旧的编译器的副本并明确使用它.

有关这个交换机所做的和不做的更多例子,请参见http://ericlippert.com/2013/04/04/what-does-the-langversion-switch-do/.

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...