在项目属性中,我选择“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/.