基于以下代码:
var grouped = filters.GroupBy(p => p.PropertyName);
int numOfRowElements = grouped.Count();
foreach (IGrouping<string, PropertyFilter> filter in grouped)
{
foreach (var propertyFilter in filter)
{
// do something
}
}
过滤List,我的理解是调用IEnumerable.Count()会强制执行查询。执行的结果是否存储在分组变量中,然后在foreach循环中使用,还是foreach循环强制再次执行查询?这样做会不会更好?
var grouped = filters.GroupBy(p => p.PropertyName).ToList();
int numOfRowElements = grouped.Count;
foreach (IGrouping<string, PropertyFilter> filter in grouped)
{
foreach (var propertyFilter in filter)
{
// do something
}
}
TIA。
如果底层数据源是IList<T>
, Enumerable.Count()
将调用.Count
属性作为优化,因此没有性能损失。如果不是,将强制进行枚举。请仔细考虑这一点。
var someList = new List<int>();
var count = someList.Count(); // will use .Count property
var count = someList.OrderBy(x => x).Count(); // will force enumeration
在本例中,我只是在第二个语句中获取列表的计数。在第三个代码中,我对列表进行排序,然后获得计数。对列表排序返回一个序列,而不是列表。因此,Count()
方法不是作用于IList<T>
,而是IEnumerable<T>
。在这种情况下,必须枚举查询以获取结果,并将产生相应的成本(在本例中是排序)。
鉴于此,在第一个代码片段中,将枚举查询两次。一次得到计数,一次在foreach中。这将执行将数据分组两次的所有逻辑。第二个示例将只执行一次分组操作,同时在foreach中迭代结果列表,这应该比第二次执行分组操作要便宜。(是否可以衡量节省将完全取决于原始列表中数据的大小和/或来源。如果有疑问,请配置它)
*对于间接层可能有一个小的测量惩罚,如果您认为这是一个真正的瓶颈,您必须对其进行分析。但是把Count()
方法想象成
if (sequence is IList<T>)
{
return ((IList<T>)sequence).Count
}
else
{
/* perform enumeration */;
}