出于某种原因,第二个列表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个条目,但不是吗?怎么可能?
答案 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));