Linq:切勿使用 Count() > 0 来判断集合非空
2011-12-11 20:51 鹤冲天 阅读(26924) 评论(22) 编辑 收藏 举报Linq 出现之前,我们通常使用下面的方式来判断集合是否非空,即集合包含元素:
1 2 3 4 5 6 7 8 |
var array = new int[0]; var b1 = array.Length > 0; var list = new List<string>(); var b2 = list.Count > 0; var collection = new Collection<double>(); var b3 = collection.Count > 0; |
使用 Length 或 Count 属性,上面的写法没有问题。
但到了 Linq 时代,Enumerable.Count 扩展方法“统一了“ Length 和 Count 属性,于是就有了下面判断非空的写法:
1 2 3 4 5 |
public static void SomeAction<T>(IEnumerable<T> source){ if (source.Count() > 0){ //... }//... } |
这种写法可以,运行也正常,但可能会产生非常严重的性能的问题。
注意是可能,并不是一定,上面的方法如果传入的是 Array、List<T>或Collection<T>,不会有问题。
那么什么时候会出问题呢?我们来看如下方法:
1 2 3 4 5 6 |
public static IEnumerable<int> GetNums(int start, int count) { var end = start + count; for (int i = start; i < end; i++) yield return i; } |
如下调用时:
1 2 |
var nums = GetNums(0, int.MaxValue); SomeAction(nums); |
执行速度会相当慢,我的电脑大约用了 70 秒的时间来执行 source.Count() > 0。
分析下的话,你会发现 GetNums 第 5 行代码 yield return i 执行了 int.MaxValue 次,有必要吗?
其实只要返回一个元素我们就可以断定集合非空,完全不需要将所有的元素返回。
那又如何来判断呢?我们可以使用 Enumerable.Any 扩展方法:
将 SomeAction 方法修改如下:
1 2 3 4 5 |
public static void SomeAction<T>(IEnumerable<T> source){ if(source.Any()){ // 切勿使用 source.Count() > 0 //... }//... } |
再次调用 ,你会发现执行时间可以忽略不计了。
总结下规律, Count() > 0 遇上 yeild return 必定会出现性能问题。
Enumerable.Any 扩展方法可以解决我们的问题,但这个方法在命名上似乎有些问题,总感觉有点不顺,如若判断集合为空:
1 2 |
if (!source.Any()) { //... } |
! source.Any() 更显得绕口,我们可以新增两个扩展方法 IsEmpty、IsNotEmpty 来解决,请参考我的文章:
-------------------
思想火花,照亮世界
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
2009-12-11 c# 扩展方法奇思妙用高级篇八:Type类扩展