更新: タイトルを修正したので、暴言は無視してください。
質問のタイトルは、コード サンプルとは関係ありません。あなたの質問は、1 つの構文が IEnumerable で、もう 1 つの構文が IQueryable であることを意味していますが、これは正しくありません。あなたのサンプルでdb.Surveys
は、 が IQueryable の場合、両方のサンプルが IQueryable を使用しています。私は両方の質問に答えようとします。
2 つのコード サンプルは、同じ LINQ クエリを別の方法で記述しただけです (適切に記述されていると仮定します)。The code in sample 1 is just shorthand for the code in sample 2. コンパイラは、両方のサンプルのコードを同じように扱います。int?
C# コンパイラがと同じように扱う方法を考えてみてくださいNullable<System.Int32>
。C# 言語と VB.Net 言語の両方で、この省略形のクエリ構文が提供されます。他の言語にはこの構文がない可能性があり、サンプル 2 構文を使用する必要があります。実際、他の言語は拡張メソッドやラムダ式をサポートしていない可能性があり、さらに醜い構文を使用する必要があります。
アップデート:
サンダーの例をさらに進めるには、これを書くと(クエリ内包構文):
var surveyNames = from s in db.Surveys select s.Name
コンパイラがその省略形を次のように変換すると思います(拡張メソッドとラムダ式):
IQueryable<string> surveryNames = db.Surveys.Select(s => s.Name);
しかし、実際には拡張メソッドとラムダ式は省略形そのものです。コンパイラは次のようなものを発行します (正確ではありませんが、アイデアを提供するためだけに):
Expression<Func<Survey, string>> selector = delegate(Survey s) { return s.Name; };
IQueryable<string> surveryNames = Queryable.Select(db.Surveys, selector);
クラスSelect()
の静的メソッドにすぎないことに注意してください。Queryable
.NET 言語がクエリ構文、ラムダ、または拡張メソッドをサポートしていない場合は、コードを自分で作成する必要があります。
あるスタイルを使用する利点は何ですか?
小さなクエリの場合、拡張メソッドをよりコンパクトにすることができます。
var items = source.Where(s => s > 5);
また、拡張メソッドの構文は、条件付き where 句など、より柔軟にすることができます。
var items = source.Where(s => s > 5);
if(smallerThanThen)
items = items.Where(s => s < 10);
if(even)
items = items.Where(s => (s % 2) == 0);
return items.OrderBy(s => s);
さらに、いくつかのメソッドは拡張メソッド構文 (Count()、Aggregate()、Take()、Skip()、ToList()、ToArray() など) を介してのみ使用できるため、これらのいずれかを使用すると、両方の構文が混在しないように、通常はこの構文でクエリ全体を記述します。
var floridaCount = source.Count(s => s.State == "FL");
var items = source
.Where(s => s > 5)
.Skip(5)
.Take(3)
.ToList();
一方、クエリが大きく複雑になると、特にいくつかlet
の 、group
、join
などで複雑になり始めると、クエリの理解構文がより明確になります。
最終的には、通常、特定のクエリごとに適切に機能する方を使用します。
更新:タイトルを修正したので、残りは無視してください...
さて、あなたのタイトルについて:LINQに関しては、IEnumerableとIQueryableは非常に似ています。どちらもほとんど同じ拡張メソッド (Select、Where、Count など) を持っていますが、主な (唯一の?) 違いは、IEnumerable がパラメーターFunc<TIn,TOut>
として取り、IQueryable がExpression<Func<TIn,TOut>>
パラメーターとして取ることです。どちらも同じ方法 (通常はラムバ式) で表現しますが、内部的には完全に異なります。
IEnumerable は、LINQ to Objects への入り口です。LINQ to Objects 拡張メソッドは、任意の IEnumerable (配列、リスト、反復可能なものforeach
)で呼び出すことができFunc<TIn,TOut>
、コンパイル時に IL に変換され、実行時に通常のメソッド コードのように実行されます。他の一部の LINQ プロバイダーは IEnumerable を使用しているため、実際には舞台裏で LINQ to Objects (LINQ to XML、LINQ to DataSet) を使用していることに注意してください。
IQueryable は、コードを直接実行する代わりに、クエリを調べて変換する必要がある LINQ to SQL、LINQ to Entities、およびその他の LINQ プロバイダーによって使用されます。IQueryable クエリとそのクエリExpression<Func<TIn,TOut>>
は、コンパイル時に IL にコンパイルされません。代わりに式ツリーが作成され、実行時に調べることができます。これにより、ステートメントを他のクエリ言語 (T-SQL など) に変換できます。式ツリーは、実行時に Func<TIn,TOut> にコンパイルし、必要に応じて実行できます。
違いを示す例は、OP が SQL Server で LINQ to SQL クエリの一部を実行し、オブジェクトをマネージ コードに取り込み、残りのクエリを LINQ to Objects で実行するこの質問にあります。これを実現するために必要なことは、IQueryable を IEnumerable にキャストし、切り替えが必要な場所に配置することだけです。