LINQ:使用 IEnumerable.Count() 或 IList.Count 以获得更好的性能

发布于 2024-12-07 23:35:39 字数 939 浏览 4 评论 0原文

基于以下代码:

 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
                    }

                }

wherefiltersaList,我的理解是调用 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。

Based on the following code:

 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
                    }

                }

where filters a List, my understanding is that calling IEnumerable.Count() forces the query to be executed. Is the result of this execution stored in the grouped variable, which is then used in the foreach loop, or does the foreach loop force the query to be executed again? Would it be better to do this instead?

 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谢绝鈎搭 2024-12-14 23:35:39

如果基础数据源是 IListEnumerable.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,而是IEnumerable >。在这种情况下,必须枚举查询才能获取结果,并将产生随之而来的任何成本(在本例中为排序)。

鉴于此,在第一个代码片段中,您将枚举查询两次。一次获取计数,一次在 foreach 中。这将执行将数据分组两次的所有逻辑。您的第二个示例将仅执行一次分组操作,同时显然会迭代 foreach 中的结果列表,这应该比第二次执行分组操作更便宜。 (您是否可以衡量节省量将完全取决于原始列表中数据的大小和/或来源。如有疑问,请对其进行分析。)


*可能会存在测量惩罚间接层,如果您认为这是真正的瓶颈,则必须对其进行分析。但将 Count() 方法视为

if (sequence is IList<T>) 
{
    return ((IList<T>)sequence).Count
}
else 
{
   /* perform enumeration */;
}

If the underlying datasource is IList<T>, Enumerable.Count() will invoke the .Count property as an optimization, so there is no* performance penalty. If it is not, an enumeration will be forced. Consider this carefully.

var someList = new List<int>(); 
var count = someList.Count(); // will use .Count property
var count = someList.OrderBy(x => x).Count(); // will force enumeration 

In this example, I'm just getting the count of the list in the second statement. In the third, I'm ordering the list and then getting the count. Ordering the list returns a sequence, not a list. Therefore, the Count() method is not working on an IList<T>, but an IEnumerable<T>. In this case, the query must be enumerated to acquire the result and will incur whatever cost that comes along with it (in this case, the ordering).

In light of this, in your first snippet, you will enumerate your query twice. Once to get the count, once in the foreach. This will perform all the logic to group your data twice. Your second example will perform the grouping operations just once, while obviously iterating over the resulting list in the foreach, which should be less expensive than also performing the grouping operation a second time. (Whether you can measure a savings will entirely depend upon the size and/or source of the data in the original list. When in doubt, profile it.)


*There may be a small measured penalty for the layer of indirection, you'll have to profile this if you believe it is a true bottleneck. But think of the Count() method as

if (sequence is IList<T>) 
{
    return ((IList<T>)sequence).Count
}
else 
{
   /* perform enumeration */;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文