LINQ:使用IEnumerable.Count()或IList.计算更好的性能



基于以下代码:

 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 */;
}

最新更新