空の転送を確認します

最近、1つのプログラムのコードを解析しているときに、次のようなメソッドに気付きました。

public void Foo<T>( IEnumerable <T> items)
{
if (items == null || items.Count() == 0)
{
//
}
}



このメソッドは一般的な列挙を受け入れ、空かどうかを確認します。 ここに潜在的な問題がありますか? 問題はこの行にあります:

  items.Count()== 0 


そして、ここでの問題は何ですか? 問題は、この行が非常に非効率になる可能性があることです。

メソッドを呼び出して、 ICollection <T>を実装していない列挙(Entity FrameworkへのクエリのIQueryable結果やLINQ to SQLなど)を渡すと、 Count()メソッドはこのチェックを実行するためにコレクション全体を反復処理します。

列挙がICollection <T>を実装する場合、すべてが正常ですCount()メソッドは、このような場合に最適化されており、 Countプロパティをチェックします

人間の言葉で言えば、私たちのラインリストの量はゼロに等しいですか?」という質問に答えます。 「。 しかし、これは私たちの興味を引くものではありません。 実際、「 列挙に少なくとも1つの要素がありますか? 」という質問に答える必要があります。 「。

この方法でタスクにアプローチすると、ソリューションが明らかになります。System.Linq名前空間のAny拡張機能を使用します。

public void Foo<T>( IEnumerable <T> items)
{
if (items == null || !items.Any())
{
//
}
}



このメソッドの利点はIEnumerableインターフェイスのMoveNextを 1回だけ呼び出す必要があることです! 無限に大きな列挙がある場合がありますが、 Anyはすぐに結果を返します。

そのようなチェックは常に使用されるため、単純な拡張メソッドの実装を検討するのがさらに良いでしょう。

public static bool IsNullOrEmpty<T>( this IEnumerable <T> items)
{
return items == null || !items.Any();
}



さて、このメソッドを使用すると、ソースコードはさらに簡単になります。

public void Foo<T>( IEnumerable <T> items)
{
if (items.IsNullOrEmpty())
{
//
}
}



ツールキットでこの拡張メソッドを使用すると、無効な列挙を非効率的にチェックすることはありません。

Source: https://habr.com/ru/post/J97464/


All Articles