在 .NET 3.5 和 4.5 中,LINQ 查询结果的差异

本文关键字:结果 查询 LINQ NET | 更新日期: 2023-09-27 18:30:23

我用 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# 编译器版本 4.0.30319.17929,输出9 8 7 6 5 4 3 2 1 0

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

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

在 .NET 3.5 和 4.5 中,LINQ 查询结果的差异

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

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

以下是埃里克·利珀特(Eric Lippert)对原始问题的看法。

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

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

有关更多信息,请参阅 Eric Lippert 的精彩博客文章

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

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