我有一个List<Order>
,我试图使用LINQ对此进行过滤:
var grouped = from o in orders
group o by o.OrderNumber into g
select new { Id = g.Key, Orders = g };
var GroupedList = grouped.ToList();
int max = GroupedList.Count();
int count = 0;
var filtered =
from g in GroupedList
where IncrementProgress(max, ref count)
select g.Id;
var filteredOrders = orders.Where(o => filtered.Contains(o.OrderNumber));
在
IncrementProgress
内部,将count
和max
打印到调试输出。 max
在我的测试3500中,我从150000的count
获取输出并计数。有人知道为什么吗?
PS:在我的生产代码中,有过滤器逻辑而不是
IncrementProgress
。更新:
这是
IncrementProgress
方法:private bool IncrementProgress(int max, ref int count)
{
Debug.WriteLine("Filtering {0} of {1}", ++count, max);
return true;
}
最佳答案
这是因为LINQ是惰性的,并且filtered
不是集合-它是一个内存中查询,它仅存储如何评估结果的信息,而不是结果本身。因此,每次使用filtered
都会对其进行重新评估,遍历GroupedList
并再次检查where
条件。
这意味着,where
条件将被评估orders.Count() * GroupedList.Count()
次。
将ToList()
调用添加到filtered
进行评估。
var filtered =
(from g in GroupedList
where IncrementProgress(max, ref count)
select g.Id).ToList();
但是,由于以后仅在
Contains
上使用filtered
,因此应使用HashSet<int>
存储结果。它将使Contains
调用O(1)而不是O(n),这将大大提高性能。var filtered =
new HashSet<int>(from g in GroupedList
where IncrementProgress(max, ref count)
select g.Id);
关于c# - 子句比项目计数更频繁地调用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22884250/