Linq没有填充其他列表

时间:2015-04-09 23:08:12

标签: c# linq

出于某种原因,第二个列表List2未填充,应该填充。

        var List1 = new List<object1>();
        //populated List1 here

        var List2 = new List<object1>();

        List1.OrderByDescending(o => o.Cnt).Take(10).Select(s =>
        {
            List2.Add(s);
            return s;
        });

List2现在应该有10个条目,但不是吗?怎么可能?

4 个答案:

答案 0 :(得分:2)

它不起作用,因为LINQ表达式被懒惰地评估。 Select函数实际上并没有执行,直到你迭代它,这是你永远不会执行的。

如果您在最后添加.ToList();,您应该会看到它正常工作。

然而,这不是您尝试做的事情的惯用方法。正如评论者所说,这样的事情会好得多:

var List2 = List1.OrderByDescending(o => o.Cnt).Take(10).ToList();

或者将值添加到已填充的列表中

List2.AddRange(List1.OrderByDescending(o => o.Cnt).Take(10));

答案 1 :(得分:2)

这是因为Linq静态函数正在使用Lazy执行,这意味着它们只在需要时执行代码。

这意味着只有当您使用Count()ToList()等方法时,.NET才能为您提供所需的结果并开始执行您想要的代码。

您可以通过将.ToList()添加到.Select()的末尾来获得所需的结果。

但更好的解决方案是使用其他方式。

答案 2 :(得分:2)

这是一个懒惰的评估问题。您没有对Select执行任何操作,因此添加不会发生。如果你这样做,它将起作用:

var resultList = List1.OrderByDescending(o => o.Cnt).Take(10).Select(s =>
{
    List2.Add(s);
    return s;
}).ToList();  //Now List2 has 10 items.

答案 3 :(得分:2)

这种情况发生了,因为可以对懒惰进行评估。 Select中的代码仅在您开始迭代可枚举时执行(即使用它)。

这允许您创建可以(可能)返回无限数量结果的枚举,例如:

public static class MyInfiniteEnumerable
{
    public static IEnumerable<int> GetIt()
    {
        var x = 0;
        while (true)
            yield return x + 1;
    }
}

在您的代码中,要开始填充List2,您需要通过迭代其元素来“消耗”IEnumerable,直到它完成为止。例如:

var myEnum = List1.OrderByDescending(o => o.Cnt).Take(10).Select(s =>
{
    List2.Add(s);
    return s;
});
foreach (var e in myEnum)
    ; // do nothing, just iterate.

更有用的是:

var list2 = List1.OrderByDescending(o => o.Cnt).Take(10).ToList();

或者

list2.AddRange(List1.OrderByDescending(o => o.Cnt).Take(10));