1

List<T>1000個のアイテムが含まれているとします。

次に、これをこのリストをフィルタリングするメソッドに渡します。さまざまなケース(たとえば、50のList<T>場合があります)を通過すると、最大50のさまざまなLinqWhere()操作が実行される可能性があります。

私はこれをできるだけ早く実行することに興味があります。List<T>したがって、 aが実行されるたびにこれをフィルタリングしたくありませんWhere()

List<T>基本的に、すべてのフィルターが適用されるまで、の実際の操作を延期するために必要です。

これはコンパイラによってネイティブに行われますか?または、が返されるIEnumerableで.ToList()を呼び出すときList<T>.Where()、またはXで操作を実行する必要がありますWhere()(X = List.AsQueryable())?

これが理にかなっていることを願っています。

4

3 に答える 3

4

はい、遅延実行はネイティブでサポートされています。リストにクエリまたはラムダ式を適用するたびに、クエリは、クエリで.ToList()を呼び出したときにのみ実行されるすべての式を保存します。

于 2010-06-17T10:27:10.860 に答える
3

を呼び出すたびにWhere、フィルターとそれが呼び出されているシーケンスを認識している新しいオブジェクトが作成されます。

この新しいオブジェクトが値を要求されると(そして、ここではイテレーターとイテレーターの間で意図的にあいまいになっています)、元のシーケンスに次の値を要求し、フィルターをチェックして、値を返すか、繰り返して戻ってきます。次の値の元のシーケンスなど。

したがって、Where50回呼び出すと(のようにlist.Where(...).Where(...).Where(...)、返されたアイテムごとに少なくとも50回コールスタックを上下する必要があるものになります。パフォーマンスにどの程度の影響がありますか?わかりません:必要がありますそれを測定します。

考えられる代替案の1つは、式ツリーを作成し、それを最後にデリゲートにコンパイルしてから、呼び出すことWhereです。これは確かにもう少し手間がかかりますが、最終的にはより効率的になる可能性があります。事実上、これを変更することができます:

list.Where(x => x.SomeValue == 1)
    .Where(x => x.SomethingElse != null)
    .Where(x => x.FinalCondition)
    .ToList()

の中へ

list.Where(x => x.SomeValue == 1 && x.SomethingElse != null && x.FinalCondition)
    .ToList()

多くの「where」フィルターを組み合わせるだけであることがわかっている場合は、を経由するよりも効率的になる可能性がありIQueryable<T>ます。いつものように、より複雑なことをする前に、可能な限り単純なソリューションのパフォーマンスを確認してください。

于 2010-06-17T10:53:28.867 に答える
0

質問とコメントには多くの失敗があります。答えは良いですが、失敗を突破するのに十分なほど強く打たないでください。

リストとクエリがあるとします。

List<T> source = new List<T>(){  /*10 items*/ };
IEnumerable<T> query = source.Where(filter1);
query = query.Where(filter2);
query = query.Where(filter3);
...
query = query.Where(filter10);

[遅延評価]はコンパイラによってネイティブに実行されますか?

いいえ。遅延評価は、Enumerable.Whereの実装によるものです。

このメソッドは、遅延実行を使用して実装されます。即時戻り値は、アクションの実行に必要なすべての情報を格納するオブジェクトです。このメソッドで表されるクエリは、GetEnumeratorメソッドを直接呼び出すか、Visual C#のforeachまたはVisualBasicのForEachを使用して、オブジェクトが列挙されるまで実行されません。


List.AsQueryable()。ToList()の呼び出しに速度のペナルティがあります

呼び出さないAsQueryableでください。使用する必要があるのはEnumerable.Where


したがって、50コールの深いコールスタックを防ぐことはできません

呼び出しスタックの深さは、最初に非常に効果的なフィルターを使用するよりもはるかに重要ではありません。早い段階で要素の数を減らすことができれば、後でメソッド呼び出しの数を減らすことができます。

于 2010-06-17T14:23:46.503 に答える