为什么c#Linq在包含List的List中使用引用而不是值

时间:2013-10-16 12:47:07

标签: c# linq list

我遇到这个简单代码的问题,我不明白为什么c#会这样做。

问题似乎是c#在列表中使用列表时使用Linq表达式引用而不是值。

在数字循环中,我根据列表选择数字,它们都存在,所以所有数字都应该添加到列表{1,2,3}中。

当您在控制台中看到数字循环中显示{1,2,3}的输出时,行为正常。

问题出现在列表的循环上,在这里似乎Linq只将最后一个数字添加到列表中,因此输出{3,3,3}。

我知道我不需要列表中的整数列表,但这只是为了证明这一点非常奇怪,这是一个已知的“错误”吗?

编辑:这似乎是它应该在5.0之前的c#中工作的方式。 在C#5.0(VS2012 +编译器)中,此行为已被修改为我期望的

static void Main()
{
    var list = new List<IEnumerable<int>>();
    var numbers = new[] {1, 2, 3};
    var numbers2 = new[] {1, 2, 3};

    foreach (var number in numbers)
    {
        var result = from s in numbers2
                     where s == number
                     select s;

        Console.WriteLine(result.First()); // outputs {1,2,3}
        list.Add(result);
    }

    foreach (var num in list)
    {
        Console.WriteLine(num.First()); // outputs {3,3,3}
    }
}

输出

  

1   2   3   3   3   3

4 个答案:

答案 0 :(得分:8)

list.Add(result);

不符合您的期望。它不会添加数字列表。 添加查询查询按需执行 。因为,在最终输出循环number = 3中,所有三个查询都返回3

如果要添加列表,请通过向其添加ToList来强制立即执行查询:

list.Add(result.ToList());

答案 1 :(得分:2)

是的,众所周知。我相信它已在c#5修复。

您可以在foreach中声明一个值,然后在Console.WriteLine中使用该值来仅使用num的结束值来停止它。

请参阅此内容以获得更清晰的解释。 The foreach identifier and closures

答案 2 :(得分:2)

执行查询时, number == 3.

这是因为第一个foreach循环已经执行,而 number 的最后一个赋值实际上是3。

LINQ查询在必要时延迟执行(例如,当您调用ToList()时)。

这不是一个奇怪的结果,这就是它的意思。

顺便说一下,在C#5.0(VS2012 +编译器)中,这种行为已被修改为你所期望的。

答案 3 :(得分:1)

只有在需要结果时才执行linq表达式。

所以

var result = from s in numbers2
where s == number
select s;
当需要result的值时,将执行

。但是,如果要立即计算表达式,则需要从中获取结果并创建对象。

var result = (from s in numbers2
where s == number
select s).ToList();

如果你想看到一个正确的流程,那么在“from s in numbers2 ....”的行上设置一个断点,看看它什么时候被击中......

希望它有所帮助...