2

LINQ と where ステートメントについて質問があります。次のコード サンプルがあります (これは、アプリケーションで使用するコードの簡略化されたバージョンです)。

// Get the images from a datasource.
var images = GetImages(); // returns IEnumerable<Image>

// I continue processing images until everything has been processed.
while (images.Any())
{
    // I'm going to determine what kind of image it is and do some actions with it.
    var image = images.First();

    // Suddenly in my process I'm going to add a where statement to my images collection to fetch all images that matches the specified criteria.
    // It can happen (if my images collection is not empty) that the same where statement will be executed again to the images collection.
    // This is also where the problem is, somehow when I don't add the ToList() extension method, my linq statement is becoming slow, really slow.
    // When I add the ToList() extension method, why is my linq statement running fast again?
    var saveImages = images.Where(<criteria>); //.ToList() this is needed to make my LINQ query performant again.

    // I'm going to do something with these save images and then I'm going to remove these save images from the current images collection because I do not need to do these anymore by using the following statement.
    images = images.Except(saveImages);
}

ToList() 拡張メソッドを追加すると、LINQ ステートメントが再び高速になる理由がコード サンプルで説明されています。IEnumerable コレクションを返すという理由だけで Where ステートメントを使用できないのはなぜですか?

私は本当に混乱していて、誰かが私にそれを説明してくれることを願っています:)。

4

2 に答える 2

5

ループを通過すると、images最初はこれになります

images.Except(firstSetOfExclusions)

それからこれ

images.Except(firstSetOfExclusions).Except(secondSetOfExclusions)

それからこれ

images.Except(firstSetOfExclusions).Except(secondSetOfExclusions).Except(thirdSetOfExclusions)

等々。速度が遅いのは、 を呼び出さない限りToList、各除外セットが新しいクエリを実行する必要があるためです。これは、基本的に同じクエリを何度も実行するため、ループを繰り返すたびに遅くなります。ToListメモリ内のクエリを「実体化」することで修正します。

この問題の別の解決策は、次のように新しい画像のサブセットを「実体化」することです。

images = images.Except(saveImages).ToList();

これにより、「except」の連鎖が回避されるため、 を呼び出す必要がなくなりToListますsaveImages

于 2013-05-08T10:29:36.207 に答える