在 System.Linq
命名空间中,我们现在可以扩展 IEnumerable
以使用 Any()
和 Count()
扩展方法 .
我最近被告知,如果我想检查一个集合中是否包含一个或多个项目,我应该使用 .Any()
扩展方法而不是 .Count() > 0
扩展方法,因为 .Count()
扩展方法必须遍历所有项目 .
其次,一些集合具有 Count
或 Length
的属性(不是扩展方法) . 使用它们会更好吗,而不是 .Any()
或 .Count()
?
是啊/是?
8 回答
好吧,
.Count()
扩展方法不会使用.Count
属性,但我会假设您不会将.Count()
方法用于简单集合,而是使用带有过滤条件的LINQ语句的末尾等 .在这种情况下,
.Any()
将比.Count() > 0
更快 .您可以进行简单的测试来解决这个问题:
检查testCount和testAny的值 .
关于 Count() 方法,如果 IEnumarable 是 ICollection ,那么我们不能遍历所有项目,因为我们可以检索 ICollection 的 Count 字段,如果 IEnumerable 不是 ICollection ,我们必须使用带有 MoveNext 的 while 迭代所有项目,看看.NET Framework代码:
参考:Reference Source Enumerable
这取决于数据集有多大以及您的性能要求是什么?
如果它没有什么巨大的使用最可读的形式,这对我来说是任何形式,因为它更短,更易读,而不是方程式 .
EDIT: 它已在EF版本6.1.1中修复 . 这个答案不再是实际的
对于SQL Server和EF4-6,Count()的执行速度比Any()快两倍 .
当你运行Table.Any()时,它会产生类似的东西(警告:不要伤害大脑试图理解它)
这需要根据您的条件进行2次扫描 .
我不喜欢写
Count() > 0
因为它隐藏了我的意图 . 我更喜欢使用自定义谓词:如果您从具有
.Length
或.Count
(例如ICollection<T>
,IList<T>
,List<T>
等)的东西开始 - 那么这将是最快的选项,因为它不需要通过所需的GetEnumerator()
/MoveNext()
/Dispose()
序列 .Any()
检查非空IEnumerable<T>
序列 .对于
IEnumerable<T>
,那么Any()
通常会更快,因为它只需要查看一次迭代 . 但是,请注意Count()
的LINQ-to-Objects实现检查ICollection<T>
(使用.Count
作为优化) - 所以如果您的基础数据源是 directly 列表/集合,那么就赢了't be a huge difference. Don' t问我为什么不这样做使用非泛型ICollection
...当然,如果你已经使用LINQ过滤它等(
Where
等),你将有一个基于迭代器块的序列,所以这个ICollection<T>
优化是没用的 .一般用
IEnumerable<T>
:坚持Any()
;-p由于这是相当受欢迎的主题和答案不同,我不得不重新审视问题 .
Testing env: EF 6.1.3,SQL Server,300k记录
Table model :
Test code:
Results:
任何()~3ms
第一次查询的Count()~230ms,第二次查询的约400ms
Remarks:
对于我的情况,EF没有像他在帖子中提到的@Ben那样生成SQL .
Note: 我在实体框架4实际时写了这个答案 . 这个答案的要点不是要进行微不足道的
.Any()
vs.Count()
性能测试 . 关键是要表明EF远非完美 . 较新的版本更好......但是如果你的代码部分速度很慢且使用EF,则使用直接TSQL进行测试并比较性能而不是依赖于假设(.Any()
总是比.Count() > 0
快) .虽然我同意大多数最高投票的答案和评论 - 特别是关于
Any
表明开发人员的意图比_233144更好 - 我的情况是,SQL在SQL Server(EntityFramework 4)上的数量级更快 .这是查询
Any
的超时异常(在~200.000记录上):Count
版本以毫秒为单位执行:我需要找到一种方法来查看两个LINQ产生的确切SQL - 但很明显在某些情况下
Count
和Any
之间存在巨大的性能差异,不幸的是,在所有情况下你似乎都不能坚持使用Any
.编辑:这是生成的SQL . 你可以看到美女;)
ANY
:COUNT
:似乎纯粹的EXISTS在哪里工作比计算Count更糟糕,然后用Count == 0做Where .
如果你们发现我的调查结果有误,请告诉我 . 无论Any vs Count讨论如何,可以从所有这些中解脱出来的是,当重写为存储过程时,任何更复杂的LINQ都会更好;) .