3

.Where()ご存知のとおり、またはのような句をコンパイル済みクエリに追加することはできません。これは.First()、クエリが変更され、再コンパイルが強制されるためです。私が知りたいのは、コンパイルされたクエリを「閉じる」ためにどのメソッドを使用できるかということです。

.AsEnumerable()ほとんどの人がまたはのいずれかを使用していることは知っています.ToList()が、他のどの方法でも同様に機能しますか?使用できますか.AsQueryable()、それともこれはノーオペレーションですか?

そして、パフォーマンスの面でどちらが優れていますか?私.AsEnumerable()はより速いことを知っています.ToList()、しかし私が欲しいならIQueryable.AsEnumerable().AsQueryable()より良いです.ToList()か?

4

2 に答える 2

7

ほとんどの場合、これAsEnumerable().AsQueryable()はおそらくあなたが望むものです。理由は次のとおりです。

  • 明示的に行うことで、基礎となる実装がノーオペレーションにAsEnumerable()なるリスクを冒さず、クエリを閉じる試みを台無しにすることはありません。AsQueryable()今日のEFがno-opを行うと言っているのではAsQueryable()なく(私が知る限り、そうではありません)、動作(no-opまたは透過的にAsEnumerable()を呼び出す)が文書化されていないだけです。それに頼るのは安全ではありません。
  • AsEnumerable()とは異なりToList()、クエリを実行するために結果セット全体をメモリにロードしません。これは、大きな結果セットでは非常に重要です。理論的には、結果セットが小さい場合、ToList()を使用することにはいくつかの利点がある可能性があります(たとえば、最適化されたToList()実装は、基になるプロバイダーから大きなチャンクでデータをプルしますが、列挙にはより多くのコンテキストスイッチングが含まれます)が、それはありそうになく、難しいようですAsEnumerable()の大規模な結果セットの利点は永遠に存続しますが、プロバイダーやバージョンによって異なります。

私が呼び出すのが好きな1つのケースはToList()、クエリを今すぐ強制的に実行したい場合です。たとえば、メソッドの早い段階でクエリのエラーをキャッチして、後でエラー処理を簡素化できるようにしたい場合や、残りのクエリを続行する前にすべての基になるデータを検証したい場合です。または、2つに切り刻んだときにクエリをより簡単にテストできる場合。そして、数百万行のクエリでToList()を呼び出すと、RAMが強制終了されるため、レコードセットが小さくなることがわかっていない限り、これを行うことはありません。

他の質問に答えるには、MSDNのLINQドキュメントのデータ型の変換で、どのLINQメソッドがクエリの実行を強制するかについて詳しく説明します。そのページによるとToArray()、、、、ToDictionary()およびToList()すべてToLookup()がクエリの実行を強制します。

対照的に、AsEnumerable()は、クエリの即時実行を強制しませんが、クエリを「閉じます」(ここで用語を使用します。これに正式な用語があるかどうかはわかりません)。http://msdn.microsoft.com/en-us/library/bb335435.aspxごと:

AsEnumerableメソッドを使用して、カスタムメソッドを非表示にし、代わりに標準のクエリ演算子を使用できるようにすることができます。

つまり、AsEnumerableを実行すると、Take()のようなすべての呼び出しが強制Where()され、一般的なLINQ実装が使用され、再コンパイルの原因となるカスタムは使用されません。

于 2010-07-26T06:05:35.440 に答える
1

コンパイルされたクエリを「閉じる」ために使用できるメソッド。

シーケンスを返すメソッドは、メソッドが。のようなものでない限り、遅延実行を使用しますToXYZWhere、、、、SelectなどがこれTakeに該当します。単一のオブジェクトを返すメソッドは、、、、、、、、、などのクエリの実行を強制します。詳細については、この優れたスレッドを参照してください。Linq-遅延実行を見つける最も簡単な方法は何ですか。SkipGroupByOrderByFirstSingleToListToArrayToDictionaryToLookupAnyAll

ほとんどの人が.AsEnumerable()または.ToList()のいずれかを使用していることは知っていますが、他のどのメソッドも同様に機能しますか?.AsQueryable()を使用できますか、それともこれはノーオペレーションですか?

それらはすべて異なります。ジャスティンは壮大な説明をしています。.ToList ()、. AsEnumerable()、AsQueryable()の違いは何ですか?良い答えがあります。


一般に、メソッド自体の名前を確認することで、メソッドのセマンティクスを理解できます。名前の付いたメソッドAsSomethingは、入力を何かとして返す以外に何もしないことを意味します。これには、新しいオブジェクトを返すことが含まれる場合と含まれない場合がありますが、参照は何らかの形で維持されます。たとえば、List<T>.AsEnumerable()単にキャストを行うだけIEnumerable<T>です(もちろん、linqコンテキストではより大きな意味があります)。List<T>どこにでも変更を反映して、キャストバックして変更することができます。それをテストするには:

var list = new List<int> { 1, 2 };
var enum = list.AsEnumerable();
var newlist = enum as List<string>;
newlist.Add(3);
//print enum.Count() -> 3

のように見えるメソッドToSomethingですが、まったく新しいオブジェクトが別のオブジェクトに変換されることがよくあります。

var list = new List<int> { 1, 2 };
var newlist = list.ToList();
newlist.Add(3);
//print list.Count -> 2

linqのコンテキスト外の何かを考えてみましょう。object.ToString()結果として新しい文字列表現が作成されます(文字列はとにかく不変なので、少し意味がありません)。興味深いセマンティクスはList<T>.AsReadonly、新しいインスタンスを返すセマンティクスですがReadOnlyCollection<T>、その外部のリストを変更すると、の内部リストも変更されるReadOnlyCollection<T>ため、という名前が付けられAsReadonlyます。

var list = new List<int> { 1, 2 };
var readonlylist = list.AsReadonly();
list.Add(3);
//print readonlylist.Count -> 3
于 2013-11-11T13:12:40.110 に答える