我只想知道 HashSet
hs
是否为空。
我没兴趣知道它到底包含多少元素。
所以我可以用这个:
bool isEmpty = (hs.Count == 0);
...或者这个:
bool isEmpty = hs.Any(x=>true);
哪一个在性能方面提供更好的结果(特别是当 HashSet 包含大量元素时)?
在 HashSet 上,您可以同时使用两者,因为 HashSet 内部管理计数。
但是,如果您的数据位于
IEnumerable<T>
或 IQueryable<T>
对象中,则使用 result.Any()
优于 result.Count()
(两种 Linq 方法)。
Linq 的
.Count()
将迭代整个 Enumerable,.Any()
只会查看 Enumerable 中是否存在任何对象。
更新: 只是小补充: 在您使用 HashSet 的情况下,
.Count
可能更可取,因为 .Any()
需要创建并返回 IEmumerator
,如果您不打算在代码中的任何地方使用枚举器(foreach
,林克等)。但我认为这将被视为“微优化”。
更新2 很长一段时间后重新审视它,在 .NET Core 的情况下,这有点棘手,但在
IEnumerabel<T>
的情况下。如果 IEnumerable<T>
是一个 HashSet 或集合,.Any()
将检查它的基础类型,并在调用时应用 .Count
(如果它是 ICollection<T>
类型),如果它确定它具有 .Count
属性,否则将循环通过可枚举来计数。
HastSet<T>
实现了 ICollection<T>
,它具有 Count
属性,因此对 Count()
的调用只会调用 HastSet<T>.Count
,我假设这是一个 O(1) 操作(这意味着它实际上并不必须 count - 它只返回 HashSet
的当前大小。
Any
将迭代,直到找到与条件匹配的项目,然后停止。
所以在你的情况下,它只会迭代一项,然后停止,所以差异可能可以忽略不计。
如果您想要应用一个过滤器(例如
x => x.IsValid
),那么Any
会肯定更快,因为Count(x => x.IsValid)
会迭代整个集合,而Any
会立即停止,如果找到匹配项。
出于这些原因,我通常更喜欢使用
Any()
而不是 Count()==0
,因为它更直接并且可以避免任何潜在的性能问题。如果它比 Count()==0
提供了显着性能提升,我只会切换到Any()
。
请注意,
Any(x=>true)
在逻辑上与调用Any()
相同。这不会改变你的问题,但没有 lambda 看起来更干净。
根据集合的类型,它可能会或可能不会影响性能。那么为什么不直接使用
hs.Any()
因为它正是为您需要了解的内容而设计的呢?
并且 lambda 表达式
x => true
在这里没有任何意义。你可以忽略它。