web-dev-qa-db-ja.com

拡張メソッドの構文とクエリの構文

標準のlinqキーワードまたはラムダ式を使用したlinq拡張メソッドを使用するのに適した時間がある場合に、ハンドルを取得しようとしています。彼らは同じことをしているようで、ただ異なって書かれています。それは純粋にスタイルの問題ですか?

var query = from p in Products
    where p.Name.Contains("foo")
    orderby c.Name
    select p;

// or with extension methods:
var query = Products
    .Where(p => p.Name.Contains("foo"))
    .OrderBy(p => p.Name);

2番目の例は少し簡潔ですが、=>が何をしているのかわからない場合、表現力が低下している可能性があります。

簡潔なコードを書く以外に、LINQ構文とは対照的に、拡張メソッドを使用することには他の利点がありますか?

65
Armstrongest

正直なところ、FuncsとActionsの使用を開始すると、状況に応じて変わることがあります。次の3つの機能を使用しているとします。

  Func<DataClasses.User, String> userName = user => user.UserName;
  Func<DataClasses.User, Boolean> userIDOverTen = user => user.UserID < 10;
  Func<DataClasses.User, Boolean> userIDUnderTen = user => user.UserID > 10;

ご覧のとおり、最初のものはlamdba式を置き換えてユーザー名を取得し、2番目はlamdba式を置き換えて、IDが10より小さいかどうかを確認するために使用します。

注:これはばかげた例ですが、動作します。

  var userList = 
    from user in userList
    where userIDOverTen(user)
    select userName;

Versus

  var otherList =
    userList
    .Where(IDIsBelowNumber)
    .Select(userName)

この例では、拡張メソッドはFuncを最大限に活用できるため、2番目は少し冗長ですが、Linq式はブール値を返すFuncではなくブール値だけを探すため、できません。ただし、ここで式言語を使用する方が適切な場合があります。すでにユーザー以上のものを取り込むメソッドがあったとします:

  private Boolean IDIsBelowNumber(DataClasses.User user, 
          Int32 someNumber, Boolean doSomething)
  {
    return user.UserID < someNumber;
  }

注:ユーザーと整数を取り込んでブール値を返すメソッドでは、where拡張メソッドが適切であるため、doSomethingがちょうどそこにあります。この例ではいらいらします。

さて、Linqクエリを見ると:

  var completeList =
     from user in userList
     where IDIsBelowNumber(user, 10, true)
     select userName;

あなたはそれでいいです。次に、拡張メソッド:

  var otherList =
    userList
    .Where(IDIsBelowNumber????)
    .Select(userName)

ラムダ式がなければ、そのメソッドを呼び出すことはできません。それで、私がしなければならないのは、元のメソッド呼び出しに基づいてFuncを作成するメソッドを作成することです。

   private Func<DataClasses.User, Boolean> IDIsBelowNumberFunc(Int32 number)
   {
      return user => IDIsBelowNumber(user, number, true);
   }

そして、それを差し込みます:

  var otherList =
     userList
     .Where(IDIsBelowNumberFunc(10))
     .Select(userName)

ご覧のとおり、時にはクエリアプローチを使用する方が簡単な場合があります。

33
Programmin Tool

LINQ拡張メソッド(メソッドベースのクエリ)を使用する利点の1つは、カスタム拡張メソッドを定義できることです。

一方、LINQ クエリ式を使用する場合、カスタム拡張メソッドはキーワードリストにありません。他のキーワードと混ぜると少し奇妙に見えます。

文字列を取るだけのIntoというカスタム拡張メソッドを使用しています。

クエリを使用した例

var query = (from p in Products
    where p.Name.Contains("foo")
    orderby c.Name
    select p).Into("MyTable");

拡張メソッドの例

var query = Products
                   .Where(p => p.Name.Contains("foo"))
                   .OrderBy(p => p.Name)
                   .Into("MyTable");

私の意見では、後者はmethod-based queryを使用しており、カスタム拡張メソッドがある場合に読みやすくなります。

24
Nathan W

それらを一緒に使用しないで、どちらかを選択してそれを使い続けるのは良い考えだと思います。

主に個人的な好みですが、クエリ構文(内包法)では、前述のようにすべての演算子が使用できるわけではありません。

拡張メソッドの構文は、残りのコードとより一致していると思います。 SQLをSQLで実行します。また、拡張メソッドを使用してすべてを追加するだけで、簡単に式を作成できます。

ちょうど私の2セント。

私はまだコメントを書くことができないので、ここでプログラミングツールの答えにコメントを付けたいと思います。最後の例のためにまったく新しい方法を作るのはなぜですか?あなただけを使用することはできません:

.Where(user => IDIsBelowNumber(user, 10, true))

14
Rodi

それらは同じものをコンパイルし、同等です。個人的には、ほとんどの場合、ラムダ(拡張)メソッドを好みます。LINQto SQLを実行している場合、またはSQLをエミュレートしようとしている場合にのみ、ステートメント(標準)を使用します。ラムダメソッドの方がコードの方が適切に動作しますが、ステートメントは視覚的に邪魔になります。

6
Mark Brackett

FirstOrDefault()などのクエリ構文に相当するものがないLinqメソッドを使用する場合は、拡張メソッド構文を使用します。

4
Eric Minkes

クエリ、つまりオンデマンドで評価する遅延式の場合、クエリ構文を使用するのが好きです。

通常のメソッド呼び出し(メソッド構文またはラムダ構文)のように見えるメソッドは、怠laに見えることはないので、慣例として使用します。たとえば、

var query = from p in Products
            where p.Name.Contains("foo")
            orderby p.Name
            select p;

var result = query.ToList(); //extension method syntax

それがクエリではない場合、私は他の熱心に実行されている呼び出しと一貫性があるように見える流fluentなスタイルが好きです。

var nonQuery = Products.Where(p => p.Name.Contains("foo"))
                       .OrderBy(p => p.Name)
                       .ToList();

これにより、2つのスタイルの呼び出しをより適切に区別できます。もちろん、とにかくメソッド構文を使用せざるを得ない状況があるので、私の慣習は十分に説得力がありません。

0
nawfal