微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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/.

原文地址:https://www.jb51.cc/csharp/95658.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐