List<T>中使用Any还是Count?

69

当我想要对列表执行某些操作时,我首先会检查它是否为null或者不包含任何元素(以免在foreach中出现问题),通常我会使用list.Any()。但是,哪种选项更好呢?是使用list.Count > 0还是使用list.Any()


1
按照编码规范,列表(集合等)永远不应该为null - 而应该为空。 - user57508
最好在可枚举对象上使用Any(),在集合上使用Count()。如果有人觉得写'(somecollection.Count > 0)'会导致混淆或可读性问题,最好将其编写为扩展方法并命名为Any()。这样每个人都满意,无论是性能方面还是可读性方面。因此,您的所有代码都将具有一致性,项目中的各个开发人员不必担心选择Count vs Any。 - Mahesh Bongani
5个回答

111
  • 如果你使用的是 List,请使用 Count,因为它知道它的大小。
  • 对于一个 Array,请使用 Length
  • 如果你只有一个 IEnumerable,建议使用 .Any() 而不是 .Count(),因为它会更快,因为它在检查一个项目后就停止了。

另外请查看这个问题:哪种方法更好:.Any() vs .Count() > 0?


2
不要这样做!如果可以的话,__始终__使用“Any”,因为它会尽可能地转换成“Count”或“Length”,并且具有清晰和统一的意图。 - TaW
9
@TaW 建议始终使用 "Any",因为它会在可能的情况下自动转换为 "Count" 或 "Length"。您能够提供一些源代码来支持这个建议吗?因为我不相信这一点。抱歉。可以看一下以下代码示例:string[] fruits = {"apple", "banana", "orange"}; // 使用 Any 方法 if (fruits.Any()) { Console.WriteLine("数组中包含元素"); } // 使用 Count 属性 if (fruits.Count() > 0) { Console.WriteLine("数组中包含元素"); } // 使用 Length 属性 if (fruits.Length > 0) { Console.WriteLine("数组中包含元素"); }上述代码演示了如何使用 Linq 的 Any 方法、Count 属性和数组的 Length 属性来检查数组是否为空。根据 Microsoft 文档,当调用 Any 方法时,如果集合包含至少一个元素,则返回 true,否则返回 false。在实际使用中,此方法在遍历集合时能够提高性能,因为它只需要找到第一个元素即可返回结果。另外,当针对某些数据类型(例如数组)使用 Any 方法时,它将自动转换为 CountLength 属性,因为它们具有相同的语义。 - Silvermind
我已经在各种评论和帖子中报告了我发现的问题,但是看到这些来源,我有些怀疑。除非涉及到访问数据库,否则我仍然建议使用Any();但对于其他情况,我怀疑是否会有任何可衡量的性能损失(不确定这些强制转换如何影响),而更清晰的代码仍然是一个好理由。 - TaW
1
@Silvermind 在当前的dotnet运行时中,将使用以下内容:https://github.com/dotnet/runtime/blob/v5.0.5/src/libraries/System.Linq/src/System/Linq/AnyAll.cs#L11-L45 至于.NET框架,则没有这样的检查,因此.Count优先于.Any()。有趣的是。 - Baklap4
1
嘿,@Baklap4。我在这里也有同样的争论,如果你阅读它,你会看到我可以让它崩溃,但我已经看到了源代码。 ;) https://stackoverflow.com/a/66824318/858757 - Silvermind
也许可以看一下这些基准测试 - Flimtix

4
我使用 list.Count > 0,因为它不依赖于LINQ方法,所以适用于C# 2.0。
我个人像避开瘟疫一样避开LINQ(因为速度慢),而且这里根本没有理由使用扩展方法。
然而,更好的解决方案可能是制作你自己的版本的Any,它将接受一个null引用,并在有元素的集合中返回true。这将节省你进行空检查的时间。

10
LINQ 可能比 for 循环等方法慢一些,但它不至于需要避免使用。我认为,尽管会稍微降低一些性能,但它让代码更易于维护,所以还是值得使用的。 - Phil

4
通常情况下,使用.Any()比使用.Count() > 0更好。原因是,如果你正在迭代的项目不是ICollection,那么它将不得不遍历整个列表才能获取计数。
但是,如果项目是ICollection(例如List<T>),则使用Count()与使用Any()一样快,甚至在某些情况下更快(在MS .Net中,Any()无论底层类型如何都只进行一次迭代,但Mono试图优化为当底层项目是ICollection时使用Count > 0)。
一个很棒的工具是Reflector,它提供了.Net源代码和Mono源代码,可以让您看到事物的实现方式。

5
顺便提一句,.NET Reflector 自 7 版本以后就不免费了,可以使用 ILSpy 作为替代品(http://wiki.sharpdevelop.net/ilspy.ashx)。 - user57508
@Andreas Niedermair:为什么你说IEnumerable<T>是邪恶的接口/类??? - Florian
@Florian pfuh ... 一年后 ... 没有计划 ... 抱歉,朋友 - 我应该删除这个评论 :) - user57508
1
从这个源代码来看,似乎Mono没有将Any()优化为Count > 0(它似乎与.net实现相同):https://github.com/mono/mono/blob/master/mcs/class/referencesource/System.Core/System/Linq/Enumerable.cs - Rick Love

2

如果您正在使用Entity Framework并且有一个包含许多记录的巨大表,则Any()将更快。我记得有一次我想检查一个表是否为空,它有数百万行。使用Count() > 0完成需要20-30秒。但是使用Any()则是瞬间完成的。


1
Any() 可以提升性能,因为它可能不需要遍历集合来获取事物的数量。它只需要命中其中一个。或者,对于 LINQ-to-Entities,生成的 SQL 将是 IF EXISTS(...) 而不是 SELECT COUNT ... 或者 SELECT * ....

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接