Linq:切勿使用 Count() > 0 来判断集合非空

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 扩展方法:

image

将 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 来解决,请参考我的文章:

c# 扩展方法奇思妙用基础篇十:IsEmpty、IsNotEmpty 扩展

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值