VS 2010和VS 2012中的不同LINQ答案



以下答案在vs 2010和vs 2012中的2中给出了1个。我个人认为应该是2。我不确定这里发生了什么。

using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System;
namespace _335ExamPreparation
{
    public class Doubts
    {
        int[] nums = { 10, 11, 12, 13, 14, 15, 16 };
        int[] divisors = { 7, 10 };
        static void Main(string[] args)
        {
            Doubts d = new Doubts();
            d.func();
        }
        public void func()
        {
            var m = Enumerable.Empty<int>();
            foreach (int d in divisors)
            {
                m = m.Concat(nums.Where(s => (s % d == 0)));
            }
            int count = m.Distinct().Count();
            Console.WriteLine(count);
        }
    }
}

谢谢。

您看到的是foreach的两个不同应用程序的结果。该行为在VS 2012中进行了更改。请参阅本文。

两者之间的差异涉及foreach环中d变量的范围和寿命。在VS 2012之前,只有一个d变量,因此,这意味着您正在创建两个闭合(s => (s % d == 0)))的副本,它们都引用了 same Same d。评估循环完成后,d为10。当您通过调用.Distinct().Count()执行查询时,两个关闭的值为d的值为10。这就是为什么计数在VS 2010上为1。

vs 2012为每个迭代生成一个不同的变量 1 ,因此每个闭合将看到d变量的不同的实例,该实例与该特定迭代相对应。

这大约是VS 2010生成的代码:

int d;
for (int _index = 0; _index < divisors.Length; ++_index) {
    d = divisors[_index];
    m = m.Concat(nums.Where(s => (s % d == 0)));
}

这大致是与2012年生成的内容:

for (int _index = 0; _index < divisors.Length; ++_index) {
    int d = divisors[_index];
    m = m.Concat(nums.Where(s => (s % d == 0)));
}

这两个之间的区别应很明显。

如果您想获得相同的行为,无论哪个VS版本,那么始终复制迭代变量:

foreach (int d in divisors)
{
    var copy = d;
    m = m.Concat(nums.Where(s => (s % copy == 0)));
}

1 从技术上讲,只有在闭合中引用迭代变量时。如果不是这样,则无需制作副本,因为这仅影响闭合语义。

最新更新