web-dev-qa-db-ja.com

Resharper:IEnumerableの可能な複数の列挙

新しいResharperバージョン6を使用しています。コード内のいくつかの場所で、テキストに下線が引かれ、IEnumerableの複数の列挙が可能の可能性があることを警告しています。

私はこれが何を意味するのかを理解しており、適切な場合にはアドバイスをとってきましたが、場合によっては、それが実際に大したことであるかどうかわかりません。

次のコードのように:

_var properties = Context.ObjectStateManager.GetObjectStateEntry(this).GetModifiedProperties();
if (properties.Contains("Property1") || properties.Contains("Property2") || properties.Contains("Property3")) {
    ...
}
_

2行目のpropertiesの言及に下線を引いて、このIEnumerableを複数回列挙していることを警告しています。

行1の終わりに.ToList()を追加すると(propertiesが_IEnumerable<string>_から_List<string>_に変わります)、警告が消えます。

しかし、確かに、それをリストに変換すると、最初にIEnumerable全体を列挙してリストを作成し、必要に応じてリストを列挙してプロパティを検索します(つまり、1つの完全列挙と3つの部分列挙) )。私の元のコードでは、3つの部分的な列挙のみを行っています。

私が間違っている?ここで最良の方法は何ですか?

37
Ross

propertiesが実際に何であるかは正確にはわかりませんが、本質的に非具体化データベースクエリを表す場合、ifステートメントは3つのクエリを実行します。

容疑者するほうが良いでしょう:

string[] propertiesToFind = { "Property1", "Property2", "Property3" };
if (properties.Any(x => propertiesToFind.Contains(x))
{
     ...
}

論理的にシーケンスを1回だけ繰り返す-データベースクエリが含まれている場合は、SQLの "IN"句を使用して、データベース内のすべてのクエリを1つのクエリで実行できる可能性があります。 。

41
Jon Skeet

IEnumerableでContains()を呼び出すと、拡張メソッドが呼び出され、アイテムを見つけるためにアイテムを反復処理します。 IListにはContains()の実際の実装があり、これは通常の値の反復よりも効率的です(ハッシュを使用した検索ツリーがある可能性があります)。したがって、IListで警告されません。

拡張メソッドはそれがIEnumerableであることを認識するだけなので、理論的には既知の型を識別してそれに応じてキャストすることは可能ですが、Contains()の組み込みメソッドを利用することはできませんそれらを活用してください。

6
jishi