C#List <>中的.Any()有什么用?


40

我一直在与同事讨论这个问题,我们无法弄清楚C#中.Any任何给定的用途是什么List<>

您可以像下面的语句那样检查数组中元素的有效性:

if (MyList.Any()){ ...}  //Returns true or false

完全一样

if (MyList.Count() != 0) { ... }

并且更加常见,易读并且清楚if声明的意图。

最后,我们陷入了这种想法:

.Any() 可以使用,但效果也一样,但是对程序员的意图尚不清楚,因此不应该使用它。

但是我们觉得这是不对的。我们一定缺少一些东西。

是吗


40
用什么方式不太清楚意图?
jk。

35
我对您的说法Any()不太明确提出质疑: Any()在我看来,尤其是在λ条件下,这种说法更加明确。我将代码翻译成英文,if(MyList.Count(o => o > 10) > 0)变成“大于10的项目数是否大于0?” if(MyList.Any(o => o > 10))变成“是否有大于10的项目?”
BlueRaja-Danny Pflughoeft 2015年

3
@SargeBorsch-仅当您更喜欢Heskel /功能命名时,大多数人都不喜欢。
DavorŽdralo2015年

4
@ BlueRaja-DannyPflughoeft我同意。我认为任何事情都更清楚,因为它消除了可以被视为幻数的数字。
安迪

2
@SargeBorsch:平行于SQL AnyIS Exists。Linq名称可能更受Haskell和Python的启发,它们也具有任何/所有功能。
JacquesB 2015年

Answers:


95

请记住,这Any不适用于List;它对进行操作IEnumerable,表示可能具有或不具有Count属性的具体类型。的确,在上使用它不一定是最好的选择List,但是在LINQ查询结束时它肯定派上用场。比独立版本更有用的是带有谓词的替代,就像Where。没有什么List比谓词Any扩展方法更方便或更具表达性的了。

另外,如果您使用Count()的是IEnumerable的LINQ扩展方法,而不是Count的属性List,则它必须枚举整个序列,如果它无法通过检测基础数据类型具有Count属性来优化此序列。如果序列很长,当您实际上并不在乎计数是什么,而只是想知道集合中是否有任何项目时,这可能会成为明显的性能下降。


19
这个。除了性能之外,Any()使用谓词比将谓词的覆盖率与0 进行比较更具表现力。Enumerable.Count():)
Dan J

1
我认为这对基本原理的解释如此清晰,充其量只能解释其答案。
塔里克

2
恕我直言,带有谓词与Exists一样方便和富有表现力AnyCount != 0在上使用属性List比使用更为正常Any()。这只是个人喜好。我还经历了更改_list_.Count()_list_.Count小组代码的工作。这对我来说有很大的不同。
Suncat2000

55

运行时间差Count()可以是O(n),其中Any()O(1)。


15
Count()对于无限迭代器,Any()它也不会停止,但会停止,因为它只需要调用MoveNext()一次。
乔恩·普迪

3
简洁准确,但这更多是作为评论而非答案。程序员更喜欢深入探讨原因 并提供解释的答案。考虑编辑答案,并扩展O(1)为什么很重要的原因。

刚刚得知的一个很好的答案,我应该使用any而不是count == 0:d
MonsterMMORPG

4
Any(Func<T>)是O(n)
BlueRaja-Danny Pflughoeft 2015年

1
在的特定情况下List,性能是相同的,因为扩展使用了属性。对于实现该ICollection接口的所有集合为True 。
Thorkil Holm-Jacobsen

9

实际上,请记住,存在List.Count属性,然后是Enumerable.Count方法。

在您的示例中,您正在使用Enumerable.Count()方法,该方法必须遍历枚举的每个项目以返回结果。这显然比调用Any()(如果存在)只需要遍历第一项要慢。

编辑:

正确地在注释中指出,如果Enumerable.Count()扩展方法检测到可枚举也恰好是,则不需要遍历所有项目ICollection<T>。因此,在使用的情况下List<T>,使用Count属性或方法实际上没有任何区别。

IEnumerable.Count来源:

public static int Count<TSource>(this IEnumerable<TSource> source) {
    if (source == null) throw Error.ArgumentNull("source");
    ICollection<TSource> collectionoft = source as ICollection<TSource>;
    if (collectionoft != null) return collectionoft.Count;
    ICollection collection = source as ICollection;
    if (collection != null) return collection.Count;
    int count = 0;
    using (IEnumerator<TSource> e = source.GetEnumerator()) {
        checked {
            while (e.MoveNext()) count++;
        }
    }
    return count;
}

很公平。那么如何使用.Count属性呢?那会不会使读取速度大大快于调用.Any()的速度呢?
吉尔·桑德

4
List<T>性能差异将是微不足道的。因此,只需使用您喜欢的内容即可。但是对于其他类型的IEnumerables,您只能在Count()(方法)和之间进行选择Any(),在这种情况下,Any()它将始终是您的用例的明显赢家,因此应被首选。对于它的价值,我认为Any()它非常可读和清晰。
斯坦(Sstan)2015年

@sstan是的,除非将ienumerable强制转换为colletlation,然后可以对其进行优化并且没有关系。
Esben Skov Pedersen

2
Count()具有相同的复杂性,因为Count对于ICollectionS,由于扩展方法然后使用属性,而不是迭代的。
Thorkil Holm-Jacobsen

Linq扩展针对已知接口(IList,ICollection)进行了优化。即使是实现细节,此处的性能讨论也是完全多余的
Gusdor 2015年

6

一个令人惊讶的问题-我发现的目的list.Any()比的目的要明确得多list.Count()!=0

目的是指:如果您阅读某人的代码(而您自己没有写代码),那么,程序员想要实现的目标以及为什么要这样写是完全显而易见的吗?如果以不必要的复杂方式解决了常见问题,您将立即感到可疑,并想知道为什么开发人员未使用这种简单方式。您遍历代码并尝试查看是否错过了某些内容。您担心更改代码,因为担心缺少一些副作用,更改代码可能会导致意外问题。

使用该Any()方法的意图很明确-您想知道列表中是否有任何元素。

Count()!=0另一方面,该表达的意图对于读者而言并不明显。当然,不难发现表达式会告诉您列表是否为空。之所以出现问题,是因为您以这种特定方式而不是使用标准方法来编写它。为什么要Count()显式使用?如果您真的只需要知道列表中是否有任何元素,那么为什么要首先计算整个列表?一旦达到1,您就已经有了答案。如果源是大型(也许是无限的)集合上的迭代器或被转换为sql,则在性能方面可能会有很大不同。因此,也许Count()的显式使用是强制执行延迟查询或遍历迭代器?

但源实际上是一个List<T>其中Count()是O(1)和没有副作用。但是,如果代码依赖于的此属性List<T>,那么为什么不使用Count-property来更清楚地表明您期望O(1)操作没有副作用?

在编写过程中,它的操作与之list.Count()!=0完全相同,list.Any()只是它不必要地更加复杂且意图不明确。


我都读为“列表中是否包含任何项目?” Count()有一个隐含的转换,我会避免使用,但是并不清楚。编译器可能会对其进行优化,这只会使它变得粗心。
Suncat2000

2

也许只是单词?Any是一个形容词,什么都没说。来自Java,我称其为isNonEmpty包含动词。SQL专家可能更喜欢EXISTS。但也许Any最适合C#系统。

无论选择什么词,一旦习惯了它,它必定会更清晰。您会问“还有more than zero啤酒瓶吗”。您是否希望one or more人们在回答“不,没有any” 之前就开始数他们?


1
从LINQ的角度来看,“ any”这个名称很有意义: Any()确实是Any(o => true)
BlueRaja-Danny Pflughoeft 2015年

我通常不会用空来描述一个可枚举的对象是否有枚举。但是对我来说,“有什么要列举的东西”似乎很自然,并且任何对任何列举都不利的行为。
安迪
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.