You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#判断IEnumerable是否为空:Count与ToList().Count性能对比

IEnumerable非空判断的性能差异与最优实现

两种写法的性能差异

  • TestProp.ToList().Count > 0:性能最差的实现。ToList()方法无论源序列实际长度是多少,都会完整枚举整个序列的所有元素,分配新的List<int>实例存储所有元素,哪怕序列只需要判断是否存在第一个元素,也会产生全量遍历开销+新集合的GC内存压力,属于完全不必要的额外消耗。
  • TestProp.Count() > 0:性能中等。LINQ的Count()扩展方法做了类型兼容优化:如果源序列实现了ICollection<T>/ICollection接口(比如List<int>、int[]、Dictionary<int,int>等常见集合类型),会直接读取接口的Count属性返回,时间复杂度O(1),没有遍历开销;但如果源序列是延迟执行的迭代器(比如yield return生成的序列、Where/Select/OrderBy等LINQ方法返回的延迟查询、EF/EF Core的数据库查询结果序列),Count()依然会完整遍历整个序列统计总元素数,时间复杂度O(N),远高于「判断是否存在元素」所需的最小操作量。

该场景下的最优实现

性能最高的判断方式是使用LINQ内置的Any()方法,完整稳妥写法为:

bool isNotEmpty = TestProp?.Any() == true;

这个写法的性能优势覆盖所有场景:

  1. 先做null容错,避免TestProp未赋值为null时抛出空引用异常
  2. Any()方法内部做了两层性能优化:
    • 如果源序列实现了ICollection<T>/ICollection接口,会直接读取Count属性判断是否大于0,时间复杂度O(1),和直接读取集合原生Count属性的性能一致
    • 如果源是延迟迭代序列,只会调用一次枚举器的MoveNext()方法,只要能获取到第一个元素就立刻返回true,不会遍历后续任何元素,时间复杂度O(1),不会产生全量遍历开销,也不会分配新的集合对象

性能排序(从高到低)

  1. TestProp?.Any() == true:全场景最优,无冗余开销
  2. TestProp?.Count() > 0:仅对已预加载的ICollection类型性能和Any()持平,对延迟序列性能差距明显
  3. TestProp.ToList().Count > 0:全场景性能最差,任何场景都不推荐使用

补充说明:哪怕这类判断执行数百、数千次,Any()的开销都可以忽略不计,完全不会成为性能瓶颈;如果是对超大延迟序列做判断,Any()和另外两种写法的性能差距可以达到几个数量级。

内容的提问来源于stack exchange,提问作者Programmerzzz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 02:30:55