Linq:切勿使用 Count() > 0 来判断集合非空
原文(http://www.cnblogs.com/ldp615/archive/2011/12/11/2284154.html)
Linq 出现之前,我们通常使用下面的方式来判断集合是否非空,即集合包含元素:
var array = new int[];
var b1 = array.Length > ; var list = new List<string>();
var b2 = list.Count > ; var collection = new Collection<double>();
var b3 = collection.Count > ;
使用 Length 或 Count 属性,上面的写法没有问题。
但到了 Linq 时代,Enumerable.Count 扩展方法“统一了“ Length 和 Count 属性,于是就有了下面判断非空的写法:
public static void SomeAction<T>(IEnumerable<T> source){
if (source.Count() > ){
//...
}//...
}
这种写法可以,运行也正常,但可能会产生非常严重的性能的问题。
注意是可能,并不是一定,上面的方法如果传入的是 Array、List<T>或Collection<T>,不会有问题。
那么什么时候会出问题呢?我们来看如下方法:
public static IEnumerable<int> GetNums(int start, int count)
{
var end = start + count;
for (int i = start; i < end; i++)
yield return i;
}
如下调用时:
var nums = GetNums(, int.MaxValue);
SomeAction(nums);
执行速度会相当慢,我的电脑大约用了 70 秒的时间来执行 source.Count() > 0。
分析下的话,你会发现 GetNums 第 5 行代码 yield return i 执行了 int.MaxValue 次,有必要吗?
其实只要返回一个元素我们就可以断定集合非空,完全不需要将所有的元素返回。
那又如何来判断呢?我们可以使用 Enumerable.Any 扩展方法:

将 SomeAction 方法修改如下:
public static void SomeAction<T>(IEnumerable<T> source){
if(source.Any()){ // 切勿使用 source.Count() > 0
//...
}//...
}
再次调用 ,你会发现执行时间可以忽略不计了。
总结下规律, Count() > 0 遇上 yeild return 必定会出现性能问题。
Enumerable.Any 扩展方法可以解决我们的问题,但这个方法在命名上似乎有些问题,总感觉有点不顺,如若判断集合为空:
if (!source.Any()) { //...
}
! source.Any() 更显得绕口,我们可以新增两个扩展方法 IsEmpty、IsNotEmpty 来解决,请参考:
《 c# 扩展方法奇思妙用基础篇十:IsEmpty、IsNotEmpty 扩展 》
Linq:切勿使用 Count() > 0 来判断集合非空的更多相关文章
- 用Count() > 0 来判断集合非空的问题
Linq 出现之前,我们通常使用下面的方式来判断集合是否非空,即集合包含元素: ]; ; var list = new List<string>(); ; var collection = ...
- mysql 5.7中 count(0) count(*) count(主键) count(非空字段)效率比较
mysql count(0) count(*) count(主键) count(非空字段) 效率比较 写代码的时候经理在背后说了一句count(0)的效率高于count(*) ,索性全部测试了一下 结 ...
- LINQ体验(2)——C# 3.0新语言特性和改进(上篇)
整体来说.Visual Studio 2008和.NET 3.5是建立在.NET2.0核心的基础之上,.NET2.0核心本身将不再变化(假设不了解.NET2.0的朋友,请參看MSDN或者一些经典的书籍 ...
- org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actua ...
- Oracle > count(*) / count(0) / count(1) | order by 1, 2
select count(*), select count(0), select count(1) from table 在统计表的行数时候,经常用到 select count(*) 然而对于行数很多 ...
- 20.org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actua ...
- 关于Hibernate级联更新插入信息时提示主键不为空的问题“org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1 ”
org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual ...
- 关于Error during managed flush [Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1]错误
控制台报错: 08:07:09.293 [http-bio-8080-exec-2] ERROR org.hibernate.internal.SessionImpl - HHH000346: Err ...
- Select count(*)、Count(1)、Count(0)的区别和执行效率比较
记得很早以前就有人跟我说过,在使用count的时候要用count(1)而不要用count(*),因为使用count(*)的时候会对所有的列进行扫描,相比而言count(1)不用扫描所有列,所以coun ...
随机推荐
- Javascript进阶篇——(DOM—getAttribute()、setAttribute()方法)—笔记整理
getAttribute()方法通过元素节点的属性名称获取属性的值.语法: elementNode.getAttribute(name) 1. elementNode:使用getElementById ...
- HTML与CSS入门——第九章 使用颜色
知识点: 1.为网站选择颜色的方法 2.颜色在Web上的工作方式 3.使用十六进制颜色值的方法 4.使用CSS设置背景.文本和边框颜色的方法 9.1 选择颜色的最佳方法: 直白地说:根据用户群体找到最 ...
- Java------------运算符优先级速记口诀
单目乘加位关系,逻辑三目后赋值. 单目:单目运算符+ –(负数) ++ -- 等 乘加(乘除加减):算数单目运算符* / % + - 位:位移单目运算符<< >> 关系:关系单 ...
- sqlite的事务
好久没用数据库,知识都忘了,之前用sqlite 逐行insert数据,发现这性能实在是太坑,10w条数据,插入大约花了100来分钟. 后来发现还有事务这么一个东西,可以大幅度降低对io的操作,测试插入 ...
- Java 中关键字transient引出序列化与反序列化
一:transient(临时的)关键字 1.transient关键字只能修饰变量,而不能修饰方法和类.注意,本地变量是不能被transient关键字修饰的. 2.被transient关键字修饰的变量不 ...
- xml解析,练习
<collection shelf="New Arrivals"><movie title="Enemy Behind"> < ...
- git merge –squash介绍
Git相对于CVS和SVN的一大好处就是merge非常方便,只要指出branch的名字就好了,如: $ git merge another $ git checkout another # modif ...
- Hdu1092
#include <stdio.h> int main() { ; while(scanf("%d",&n)){ ) {;} else{ int i,a; ;i ...
- [bzoj1002][FJOI2007 轮状病毒] (生成树计数+递推+高精度)
Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道.如下图 ...
- [原]Sublime Text3 搭建16位汇编环境(windows)
最近在学习王爽的<汇编程序>,参考<简单OS开发前奏<一>EDITPLUS+MASM32搭建汇编开发环境(16位+32位)>http://www.cnblogs.c ...