次のようなメソッドを使用してLINQクエリの評価を強制することについて受け入れられている慣行は何ToArray()
ですか?クエリの最適なチェーンを構成するための一般的なヒューリスティックはありますか? 私はよくすべてを 1 回のパスで実行しようとします。そのような場合AsParallel()
、計算の高速化に非常に優れていることに気付いたからです。クエリが副作用なしで計算を実行するが、正しいデータを取得するためにいくつかのパスが必要な場合ToArray()
、正しい方法で計算を強制するか、クエリを遅延形式のままにしておく方がよいでしょうか?
3 に答える
「実験的な」ライブラリを使用することに抵抗がない場合は、 Interactive ExtensionsライブラリのEnumerableEx.Memoize
拡張メソッドを使用できます。
この方法は、基礎となるシーケンスがオンデマンドで計算されるが、後続のパスでは再計算されない、両方の世界の最良のオプションを提供します。私の意見では、もう 1 つの小さな利点は、戻り値の型が変更可能なコレクションではないことToArray
ですToList
。
クエリを複数回評価し始めるまで、または別のフォームでそれらが必要な場合や、クロージャーでキャプチャされた変数が値を変更する危険にさらされている場合は、それ以前にクエリを遅延形式のままにしておきます。
複数回の実行を避けたい複雑なプロジェクションがクエリに含まれている場合は、評価する必要があります (たとえば、多数の要素を持つシーケンスの複雑なオブジェクトを構築する場合)。この場合、一度評価して何度も反復する方がはるかに賢明です。
結果を返す場合、または特定のタイプのコレクションを必要とする別の API に結果を渡す場合は、別の形式で結果が必要になる場合があります。
クエリがスコープ内でローカルではない変数をキャプチャする場合、変更されたクロージャへのアクセスを防止したい、または防止する必要がある場合があります。クエリが実際に評価されるまで、他のコードが「背後で」値を変更する危険があります。評価が行われると、クエリが作成されたときに存在した値ではなく、これらの値が使用されます。(ただし、これは、ローカル スコープを持つ別の変数にこれらの値のコピーを作成することで回避できます)。
通常はToArray()
、配列を必要とする API など、配列を使用する必要がある場合にのみ使用します。クエリの結果にアクセスする必要がなく、ある種の接続コンテキストに限定されない限り (LINQ to SQL または LINQ to Entities の場合のように)、単にクエリを遅延形式に保ちます。