【问题标题】:Difference in LINQ query results in .NET 3.5 and 4.5 [duplicate].NET 3.5 和 4.5 中 LINQ 查询结果的差异 [重复]
【发布时间】:2013-09-09 11:58:48
【问题描述】:

我使用 C# 3.5 和 4.0 执行了以下代码。结果完全不同。

    static void Main()
    {       
        int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        List<IEnumerable<int>> results = new List<IEnumerable<int>>();

        foreach (var num in numbers)
        {
            results.Add(numbers.Where(item => item > num));
        }

        foreach (var r in results)
        {
            Console.WriteLine("{0}", r.Count());
        }        
    }

使用 Microsoft (R) Visual C# 2008 编译器版本 3.5.30729.5420,输出为 0 0 0 0 0 0 0 0 0 0

但使用 Microsoft (R) Visual C# Compiler 版本 4.0.30319.17929,输出为 9 8 7 6 5 4 3 2 1 0

我有一个模糊的想法,这是因为延迟执行或延迟评估,但还没有清楚地理解它是如何在这里负责不同的输出的。

更正:抱歉,它是 .NET 3.5 和 4.5,还添加了编译器版本 请解释一下。

【问题讨论】:

  • 我在 3.5 和 4.0 中得到相同的输出,{ 9 8 7 ... } 你确定你没有做不同的事情吗?
  • 它给了我同样的结果....
  • 我相信这种变化发生在 4.5,而不是 4.0。
  • @JoeEnos 跟.NET的版本无关,跟使用的C#版本有关。
  • @Servy 明白了,谢谢。有时很难明确这些区别。

标签: c# .net linq


【解决方案1】:

您访问了闭包内的变量,因此不同版本的编译器的结果会有所不同。

在 C# 5.0 中,变量在循环的每次迭代中都会重新定义,而在以前的 C# 版本中,它只定义一次。

有关详细信息,请参阅 Eric Lippert 的伟大 blog post

更值得注意的是,开头段落:

更新:我们正在进行重大更改。在 C# 5 中,foreach 的循环变量在逻辑上将位于循环内部,因此闭包每次都会关闭变量的新副本。 “for”循环不会改变。我们现在让您回到我们的原始文章。

【讨论】:

  • 变量的作用域与 .NET 的版本无关。它与 C# 的版本有关。它在 C# 5.0 中进行了更改。
  • 你看过eric的博客We are taking the breaking change. In C# 5
  • @Servy 是的,我已经澄清了,谢谢。
  • 是的,在使用 .NET 3.5 编译的 VS2012 中,它可以完美运行。
  • @AlessandroD'Andria 那是因为您使用的是 C# 5.0 编译器。使用的 .NET 版本无关紧要。
【解决方案2】:

从 c# 5 开始,foreach 中的循环变量被编译为存在于循环范围内而不是循环范围之外。

这意味着当你关闭循环变量时,你会得到不同的结果。

Here's what Eric Lippert不得不说原来的问题。

【讨论】:

  • 从 C# 5.0 开始,而不是 .NET 4.0。
  • 这不能回答问题。 OP 在 c# 4.0 中询问。但是你正在使用 c# 5.0
  • OP 询问 .net4。这是观察到的结果的唯一可能性。
  • 为了兼容性使用 var t = num;在 foreach 循环中。
  • @SriramSakthivel 刚刚测试过,你是对的。
猜你喜欢
  • 2014-03-11
  • 1970-01-01
  • 1970-01-01
  • 2016-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多