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-ダニーPflughoeft

3
@SargeBorsch-ほとんどの人が好まないヘスケル/機能的な命名を好む場合のみ。
デイヴァーオドラロ

4
@ BlueRaja-DannyPflughoeft同意します。マジックナンバーと見なされるものを排除するため、いずれかがより明確だと思います。
アンディ

2
@SargeBorsch:に対応するSQL AnyExistsです。Linqの名前は、おそらくすべて/すべての機能を備えたHaskellとPythonからより影響を受けています。
ジャックB

回答:


95

; Anyでは動作しないことに注意してくださいList。で動作します。IEnumerableこれは、Countプロパティを持つ場合と持たない場合がある具象型を表します。これは必ずしもで使用するのが最良の方法ではないことは事実ですListが、LINQクエリの最後に間違いなく便利です。そして、スタンドアロンバージョンよりもさらに便利なのは、のような述語を取るオーバーライドですWhereListpredicate- Anyextensionメソッドと同じくらい便利で表現力のあるものはどこにも組み込まれていません。

また、(上のプロパティCount())ではなくCount(IEnumerableのLINQ拡張メソッドList)を使用している場合、基になるデータ型にCountプロパティがあることを検出して最適化できない場合は、シーケンス全体を列挙する必要があります。あなたが長い列を持っている場合、これはあなたが本当に数が何であるかを気にしない顕著なパフォーマンスヒットすること、およびそこにあるかどうかを知りたいことができます任意のコレクション内の項目が。


19
この。パフォーマンスは別としてAny()、述部を使用すると、述部をオーバーライドするオーバーライドを0 と比較するよりも表現力が高くなります。Enumerable.Count():)
ダンJ

1
私はこれが基本を非常に明確に説明しているので、答えをせいぜい説明していると思います。
タリク

2
私見ExistsAny、述語を使用して、と同様に便利で表現力豊かです。でCount != 0プロパティを使用するのListは、を使用するよりも普通ですAny()。個人的な好みです。また、グループのコードをに変更_list_.Count()する作業も行ってい_list_.Countます。それは私に顕著な違いをもたらしました。
-Suncat2000

55

実行時間の違いCount()はO(n)でAny()あり、O(1)です。


15
Count()また、無限のイテレータで停止することはありませんAny()が、MoveNext()一度呼び出すだけで済むため、停止します。
ジョンパーディ

3
簡潔で正確ですが、これは答えではなくコメントとして読みます。プログラマは、理由を掘り下げて 説明の尺度を提供する回答を好みます。回答を編集し、O(1)が重要である(重要である)理由を拡張することを検討してください。

非常に良い答えはちょうど私がcount == 0の代わりにanyを使用する必要があることを学びました:d
MonsterMMORPG

4
Any(Func<T>)はO(n)
BlueRaja-ダニーPflughoeft

1
の特定のケースでListは、拡張機能がプロパティを使用するため、パフォーマンスは同じです。ICollectionインターフェイスを実装するすべてのコレクションに当てはまります。
トールキルホルムヤコブセン

9

実際には、そこにあるということを覚えておいてList.Countのプロパティ、およびそこでEnumerable.Countの方法。

この例では、Enumerable.Count()メソッドを使用しています。このメソッドは、列挙のすべてのアイテムを反復処理して結果を返す必要があります。これはAny()、最初の項目が存在する場合に最初の項目を反復処理するだけでよいので、呼び出しより明らかに遅いです。

編集:

指摘されたようにEnumerable.Count()、列挙型も偶然であることを検出した場合、その拡張メソッドはすべてのアイテムを反復処理する必要はありませんICollection<T>。そのため、aの場合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 yesは、ienumerableをcollentionにキャストできる場合を除き、最適化でき、重要ではありません。
エスベンスコフペダーセン

2
Count()拡張メソッドは反復の代わりにプロパティを使用するため、s と同じ複雑さCountを持ちICollectionます。
トールキルホルムヤコブセン

Linq拡張機能は、既知のインターフェイス(IList、ICollection)に対して最適化されています。ここでのパフォーマンスの説明は、たとえ実装の詳細であっても、完全に冗長です
-Gusdor

6

驚くべき質問-私はその意図がlist.Any()より明確であることを見つけますlist.Count()!=0

意図とは、誰かのコードを読んだ場合(そして自分でそれを書いていない場合)、プログラマーが何を達成したいのか、そしてそれがそのように書かれている理由は完全に明らかですか?共通の問題が不必要に複雑な方法で解決されると、すぐに疑わしくなり、開発者がなぜ単純な方法を使用しなかったのか疑問に思います。コードを調べて、何かを見落としているかどうかを確認します。コードを変更するのが怖いのは、見逃している副作用があり、変更すると予期しない問題が発生する可能性があるためです。

このAny()メソッドを使用する意図は完全に明確です-リストに要素があるかどうかを知りたいです。

Count()!=0一方、表現の意図は読者には明らかではありません。もちろん、式がリストが空かどうかを教えてくれるのを見るのは難しくありません。質問は、標準的な方法を使用するのではなく、この特定の方法で作成するために発生します。なぜCount()明示的に使用するのですか?あなたが本当にそこにあるかどうかを知る必要がある場合は任意のリストの要素は、なぜあなたが最初のリスト全体をカウントするようにしたいですか?あなたが1に達するとすぐに、あなたはすでにあなたの答えを持っています。ソースが大きな(おそらく無限の)コレクションのイテレータであるか、sqlに変換される場合、パフォーマンスの面で大きな違いが生じる可能性があります。したがって、Count()の明示的な使用は、遅延クエリを強制的に実行したり、反復子をトラバースしたりするためですか?

しかし、ソースは実際List<T>Count()はO(1)であり、副作用はありません。しかし、コードがのこのプロパティに依存している場合、副作用のないO(1)操作を期待することをより明確に示す-propertyをList<T>使用しないのはなぜCountですか?

書かれlist.Count()!=0ているとおり、list.Any()不必要に複雑で意図が明確でないことを除いて、まったく同じです。


「リストにはアイテムが含まれていますか?」Count()使用を避けたい暗黙の変換がありますが、明確ではありません。コンパイラーはそれを最適化するかもしれません。
Suncat2000

2

たぶんそれは言葉ですか?Anyは形容詞であり、実際には何も言いません。Javaから来isNonEmptyて、動詞を含むそれを呼び出します。SQLの人は好むかもしれませんEXISTS。しかし、おそらくAnyC#システムに最適です。

単語の選択が何であれ、一度慣れれ、それもっと明確でなければなりません。「more than zeroビール瓶が残っていますか」と尋ねますか。one or more「いいえ、ありません」と答える前に、数え始めている人を期待しanyますか?


1
名前あなたはLINQの面でそれを考えるとき、「任意の」は理にかなっては: Any()本当にのショートカットですAny(o => true)
ダニーPflughoeft - BlueRaja

通常、enumerableに列挙するanytjingがあるかどうかを記述するためにemptyを使用しません。しかし、「列挙するものはありますか」は私には自然に思えます。
アンディ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.