4

私が管理しているコードには、次のような一般的なパターンがあります。特定の要素を見つけるための if を含むネストされたループです。

        foreach (Storage storage in mStorage.Values)
            foreach (OrderStorage oStorage in storage.OrderStorage)
                if (oStorage.OrderStorageId == orderStorageId)

これをLINQに変更することを考えていました:

        foreach (OrderStorage oStorage in (from storage in mStorage.Values
                                           from oStorage in storage.OrderStorage
                                           where oStorage.OrderStorageId == orderStorageId
                                           select oStorage))

しかし、ここで何が起こっているのかがわかりにくく、メモリと CPU の両方のパフォーマンスを犠牲にして、より多くのオブジェクトが作成される可能性があるため、それほど魅力的ではないようです。実際にはさらに多くのオブジェクトが作成されるのでしょうか、それとも C# コンパイラが if を内部に持つ入れ子になったループに似たコードを出力するのでしょうか?

4

1 に答える 1

14

実際にはさらに多くのオブジェクトが作成されるのでしょうか、それとも C# コンパイラが if を内部に持つ入れ子になったループに似たコードを出力するのでしょうか?

より多くのオブジェクト; 各 LINQ 操作 ( SelectMany、など) はWhere、その操作Selectの保留中のクエリを表す新しいプレースホルダー オブジェクトIEnumerable<T>になり、最終的に反復されると、それぞれがコンテキストなどと共に列挙子インスタンスになります。さらに、ホイストorderStorageIdなどのキャプチャ変数コンテキストがあります。

レギュラーforeachも列挙子インスタンスになりますが、foreachダック型の列挙子も使用できるという利点があります。つまり、列挙子ではなく列挙子List<T>を実際に使用していることを意味します。もちろん、ローカル変数 ( ) を (匿名メソッドではなく) 直接使用するということは、状態/コンテキスト オブジェクトにホイストする必要がないことを意味します。structclassorderStorageId

そうです、生foreachはより直接的で効率的です。興味深い質問は、違いは重要かということです。そうである場合もあれば、そうでない場合もあります。

于 2013-08-09T11:20:58.730 に答える