zoukankan      html  css  js  c++  java
  • 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 扩展

    -------------------

    思想火花,照亮世界

  • 相关阅读:
    BCD码、十六进制与十进制互转
    UNIX环境高级编程 使用方法
    Windows下NFS服务器SFU设置(可以共享linux系统)
    Linux学习之CentOS(一)--CentOS6.4环境搭建
    WORKGROUP无法访问,您可能没有权限使用网络资源,请与这台服务器的管理员联系以....
    嵌入式学习步骤
    asp.net core-6.Bind读取配置文件到C#实例中
    asp.net core-5.控制台读取json文件
    asp.net core-4.命令行配置
    asp.net core-3.应用程序部署到iis
  • 原文地址:https://www.cnblogs.com/ldp615/p/2284154.html
Copyright © 2011-2022 走看看