关于C#:linq查询结果在.NET 3.5和4.5中的差异

Difference in LINQ query results in .NET 3.5 and 4.5

本问题已经有最佳答案,请猛点这里访问。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    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版本,还添加了编译器版本请解释一下。


由于c_5,foreach中的循环变量被编译为存在于循环范围内,而不是在循环范围外。

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

下面是埃里克·利珀特对原始问题的看法。


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

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

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

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

UPDATE: We are taking the breaking change. In C# 5, the loop variable of a foreach will be logically inside the loop, and therefore closures will close over a fresh copy of the variable each time. The"for" loop will not be changed. We return you now to our original article.