メソッドがシーケンスIEnumerable<T>
を返すので、それが空かどうかを確認します。それをどのようにすすめますか?読みやすさとパフォーマンスの両方を求めています。
最初の最も明白な方法は、カウントがゼロより大きいことを確認することです。
if(sequence.Count() == 0)
読みやすさはまあまあですが、実際にシーケンス全体を実行する必要があるため、パフォーマンスはひどいものです。
私が時々使用する方法は次のとおりです。
if(!sequence.Any())
これは(私の知る限り)シーケンス全体を通過する必要はありませんが、読みやすさは少し逆で扱いにくいです。 (ただし、シーケンスがでない空であることを確認している場合は、はるかに読みやすくなります)。
別のオプションは、次のように、try-catchでFirst
を使用することです。
try
{
sequence.First();
}
catch(InvalidOperationException)
{
// Do something
}
非常にきれいな解決策ではなく、例外などを使用しているため、おそらくもっと遅くなります。もちろんFirstOrDefault
を使用することでそれを防ぐことができますが、シーケンスの最初の項目が実際にwasである場合に大きな問題が発生します値;)
それで、シーケンスが空かどうかを確認する他の方法はありますか?どちらを普段使いますか?どちらを使用することをお勧めしますか?
注:読みやすくするために、おそらく上記のスニペットの1つをIsEmpty
拡張メソッドですが、そのメソッド内でも何かをしなければならないので、私はまだ興味があります:p
個人的には!sequence.Any()
を使用します。
本当にが必要な場合は、いつでも独自の拡張メソッドを作成できます。
public static bool IsEmpty<T>(this IEnumerable<T> source)
{
return !source.Any();
}
それからあなたは書くことができます:
if (sequence.IsEmpty())
この実装を使用して、拡張メソッドを作成できます。
public static bool IsEmpty<T>(this IEnumerable<T> items) {
using (var enumerator = items.GetEnumerator())
{
return !enumerator.MoveNext();
}
}
呼び出しているこれらすべてのメソッドはLINQ拡張メソッドであるため、LINQプロバイダーの実装方法によって異なります。シーケンスが空かどうかを知りたい場合は、Count() == 0
またはAny() == false
が適切です。私はAny()
を好みます。
ただし、sequence
が実際のTypeによっては、LINQ拡張メソッドを使用する必要がない場合があります。つまり配列の場合は、sequence.Length
を呼び出すことができます。コレクションの場合は、sequence.Count
を使用できます。
この拡張メソッドを使用して、シーケンスがnullであるか、アイテムがないかを検出します。また、string.IsNullOrEmpty()
メソッドのように、シーケンスに少なくとも1つのアイテムがあるかどうかを検出します。
public static bool IsNullOrEmpty<TSource>(this IEnumerable<TSource> source) {
if (source == null) {
return true;
}
return !source.Any();
}
public static bool IsNotNullOrEmpty<TSource>(this IEnumerable<TSource> source) {
return !source.IsNullOrEmpty();
}
.
.
.
if (!sequence.IsNullOrEmpty()) {
//Do Something with the sequence...
}
あなたが言った:
if(sequence.Count() == 0)
読みやすさはまともですが、実際にシーケンス全体を実行する必要があるため、パフォーマンスはひどいものです。
それは本当ですか?あなたはInterface、IEnumerable<T>
の扱いについて話しているが、その実装に関して、真である場合とそうでない場合があると仮定している。実際、私が長年にわたって作成してきたカスタムコレクションの多くは、現在のカウントを内部的に格納するプライベート変数を保持しています。つまり、.Count
を返すことは、コレクション全体を繰り返す必要がない簡単な問題です。
つまり、特定の実装が.Count
に対して最適化されていないことがわかっている場合を除き、.Count
を使用します。可能な限り早期の最適化を避け、読みやすさを維持します。
私が時々使用する方法は次のとおりです。
if(!sequence.Any())
❶ これは(私の知る限り)シーケンス全体を実行する必要はありません。 ❷ しかし、読みやすさは少し後ろ向きで扱いにくいです。 (ただし、シーケンスが空でないことを確認している場合は、読み取りが大幅に向上します)。
source
の列挙は、結果を判別できるとすぐに停止されます。
これは、if-else
ステートメント内の要素の存在をテストする場合に特に当てはまります。おそらく、読みやすさは、if
ステートメントの要素の存在とelse
の要素の不在をテストして、!
演算子の使用を回避する場合に最適です。
if (sequence.Any())
{
}
else
{
}
ほとんどの人はそれをもっと読みやすいと考えています:
if (!sequence.Any())
{
}
else
{
}