1. ホーム
  2. c#

LINQクエリで2つの "where "句または"&&"を使用する必要がありますか?

2023-08-09 04:41:26

質問

LINQクエリで複数の"and"条件を記述する場合、1つの"and"条件を記述すればよいのでしょうか。 where 節に && または複数の where 節が必要でしょうか?

static void Main(string[] args)
{
    var ints = new List<int>(Enumerable.Range(-10, 20));

    var positiveEvensA = from i in ints
                         where (i > 0) && ((i % 2) == 0)
                         select i;

    var positiveEvensB = from i in ints
                         where i > 0
                         where (i % 2) == 0
                         select i;

    System.Diagnostics.Debug.Assert(positiveEvensA.Count() == 
                                         positiveEvensB.Count());
}

の間に、個人的な好みやコーディングスタイル(長い行や読みやすさなど)以外の違いはあるのでしょうか? positiveEvensA positiveEvensB ?

思いつく違いの1つは、LINQプロバイダによって、複数の where より複雑な式ではなく、複数のを扱うことができるかもしれません。

どのように解決するのですか?

私は個人的には、文が意味不明にならない限り、常に && と2つの where 節を使うことにしています。

あなたの場合、おそらくまったく気づかないでしょうが、2 つの where 節を持つことは、大きなコレクションを持っている場合、そしてこのクエリからすべての結果を使用する場合、間違いなくパフォーマンスに影響を与えるでしょう。 たとえば、結果に対して .Count() を呼び出したり、リスト全体を繰り返し処理したりすると、最初の where 節が実行され、新しい IEnumerable<T> が作成され、2 番目の委譲を使用して再び完全に列挙されます。

2つの句を連結することで、クエリは1つのデリゲートとなり、コレクションが列挙されるときに実行されるようになります。 この結果、コレクションの列挙は1回となり、結果が返されるたびにデリゲートが1回呼び出されることになります。

これらを分割すると、状況は変わります。 最初のwhere節が元のコレクションを列挙すると、2番目のwhere節はその結果を列挙します。 これにより、潜在的に(最悪の場合)、コレクションを2回完全に列挙し、メンバーごとに2つのデリゲートを呼び出すことになり、この文は(理論的には)実行速度が2倍になる可能性があることを意味します。

2 つの where 節を使用することにした場合、より制限の多い節を最初に配置すると、2 番目の where 節は最初の節を通過した要素に対してのみ実行されるため、かなり助けになります。

さて、あなたのケースでは、これは問題ではないでしょう。 大規模なコレクションでは、問題になる可能性があります。 一般的な経験則として、私は次のようにします。

  1. 読みやすさと保守性

  2. 性能

この場合、どちらの選択肢も同じように保守可能だと思うので、よりパフォーマンスの高い選択肢を選ぶと思います。