web-dev-qa-db-ja.com

LINQ:ドット表記とクエリ式

私は一般にLINQを使い始めています(これまでのところ、toXMLとtoSQL)。同じ結果を得るには、2つ以上の方法がある場合があります。この単純な例を考えてみましょう。私が理解している限り、両方ともまったく同じものを返します。

SomeDataContext dc = new SomeDataContext();

var queue = from q in dc.SomeTable
        where q.SomeDate <= DateTime.Now && q.Locked != true
        orderby (q.Priority, q.TimeCreated)
        select q;

var queue2 = dc.SomeTable
        .Where( q => q.SomeDate <= DateTime.Now && q.Locked != true )
        .OrderBy(q => q.Priority)
        .ThenBy(q => q.TimeCreated);

同じことを表現するには2つの方法があるという考え方です。最初の方法にはいくつかの制限があり、「ドット表記」がより完全であることを理解していますが、それ以外に他の利点はありますか?

56

「ドット」表記は通常Lambda構文と呼ばれます。最初の表記はいくつかの名前で書かれていますが、通常はクエリ構文と呼びます。

私は10人の開発者のチームで作業しており、標準として使用する必要があるものについて詳細に議論しています。一般に、ベテラン(LINQを使用)の開発者はLambda構文に移行しますが、大きな例外があります。

Lambdaはより簡潔ですが、複数のテーブル結合を実行することは悪夢です。クエリ構文を使用すると、結合がより明確になります。反対に、Lambda構文内にのみ存在するLINQ操作がいくつかあるということです:Single()、First()、Count()など。

したがって、最も快適に感じるものを使用し、経験を積むにつれて好みが変わる可能性があることを認識してください。両方を読むことができることには大きな価値があり、両方を少し使用しなければならない状況が確かにあります。他の状況では、他の状況よりも1つのスタイルに適しています。最後に、すべてが同じ実行可能コードに変換されます。

53
andleer

ケースバイケースで、クエリに対してより読みやすい構文を使用します。

ときどきでも大丈夫ですが(たとえば、クエリの最後でFirst()を1回呼び出した場合)、可能であれば、2つを混ぜて一致させないようにします。遅延実行とは、クエリ式を使用して結果を変数に割り当て、ドット表記singその変数を使用するのと同じくらい効率的であることを意味します。

var query = from x in y
            orderby z
            group x by x.Name into groups
            // etc
            select foo;

var page = query.Skip(50).Take(10);

他の人が言ったように、クエリ式はクエリ式なしで「通常の」C#3に変換されるだけなので、これを行うためのペナルティはありません。

28
Jon Skeet

まあ、「ドット」表記はもっと短くなることがあります。取る:

var result = from p in dc.Products
             where p.Id > 5
             select p;

または:

var result = dc.Products.Where(p => p.Id > 5);

後者ははるかに短く、読みやすいので、後者を好みます。

8
Razzie

Lambda表記はより簡潔で簡潔です。 Lambda式anywhereがメソッド呼び出し内にある場合、デバッグモードでその場でコードを変更できないことは、私を困らせるだけです...

3
Shaul Behr

同じコードにコンパイルするか、最初に最初のコードを2番目に変換してからコンパイルします。

違いは、最初のバージョンはよりクリーンですがより制限されているということです。 2番目では、たとえば、既存のデリゲートを使用できます。例:

Func<int, bool> isEven = i => i%2 == 0;
Enumerable.Range(10).Where(isEven).ToList().ForEach(Console.WriteLine);
2
user76035