wake-up-neo.com

Erweiterungsmethoden-Syntax vs. Abfragesyntax

Ich versuche, einen Überblick darüber zu bekommen, ob es Zeit ist, standardmäßige linq-Schlüsselwörter oder linq-Erweiterungsmethoden mit Lambda-Ausdrücken zu verwenden. Sie scheinen dasselbe zu tun, sie werden nur anders geschrieben. Ist es nur eine Frage des Stils?

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);

Sie sind sich sehr ähnlich, das zweite Beispiel ist etwas knapper, aber weniger ausdrucksstark, wenn Sie nicht wissen, was das => tut.

Gibt es, anders als das Schreiben von Code, andere Vorteile als die LINQ-Syntax?

63
Armstrongest

Ehrlich gesagt, kann es manchmal situativ sein, wenn Sie Funcs und Aktionen verwenden. Angenommen, Sie verwenden diese drei Funktionen:

  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;

Wie Sie sehen, ersetzt der erste den Lamdba-Ausdruck, um den Benutzernamen zu erhalten, und der Zweite ersetzt einen Lamdba-Ausdruck, mit dem überprüft wird, ob die ID unter 10 liegt, und der dritte sollte jetzt leicht verständlich sein.

HINWEIS: Dies ist ein dummes Beispiel, aber es funktioniert.

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

Versus

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

In diesem Beispiel ist das zweite etwas weniger ausführlich, da die Erweiterungsmethode die Funktion Func voll ausnutzen kann. Der Linq-Ausdruck kann jedoch nicht verwendet werden, da er nur nach einem Boolean-Wert und nicht nach einem Func sucht, der Boolean zurückgibt. Hier kann es jedoch besser sein, die Ausdruckssprache zu verwenden. Angenommen, Sie hatten bereits eine Methode, die mehr als nur einen Benutzer aufnimmt:

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

Hinweis: doSomething ist einfach da, weil die Erweiterungsmethode where mit einer Methode in Ordnung ist, die einen Benutzer und eine Ganzzahl aufnimmt und boolean zurückgibt. Irritierend für dieses Beispiel.

Wenn Sie sich nun die Linq-Abfrage ansehen:

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

Du bist gut dafür. Nun die Erweiterungsmethode:

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

Ohne einen Lambda-Ausdruck kann ich diese Methode wirklich nicht nennen. Jetzt muss ich eine Methode erstellen, die eine Func basierend auf dem ursprünglichen Methodenaufruf erstellt.

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

Und dann steck es ein:

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

Sie sehen also, manchmal ist es manchmal einfacher, den Abfrageansatz zu verwenden.

33
Programmin Tool

Ein Vorteil der Verwendung von LINQ-Erweiterungsmethoden ( methodenbasierte Abfragen ) besteht darin, dass Sie benutzerdefinierte Erweiterungsmethoden definieren können und trotzdem gut lesbar sind.

Wenn Sie dagegen einen LINQAbfrageausdruck verwenden, befindet sich die benutzerdefinierte Erweiterungsmethode nicht in der Schlüsselwörterliste. Es wird mit den anderen Schlüsselwörtern gemischt aussehen. 

Beispiel

Ich verwende eine benutzerdefinierte Erweiterungsmethode namens Into, die nur eine Zeichenfolge verwendet:

Beispiel mit Abfrage

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

Beispiel mit Erweiterungsmethoden

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

Meines Erachtens liest sich letztere mit einer methodenbasierten Abfrage besser, wenn Sie benutzerdefinierte Erweiterungsmethoden haben.

24
Nathan W

Ich denke, es ist eine gute Idee, sie nicht zusammen zu verwenden und eine zu wählen und dabei zu bleiben.

Meistens ist es persönlicher Geschmack, aber in der Abfragesyntax (Comprehension-Methode) sind nicht alle Operatoren verfügbar, wie zuvor gesagt.

Ich finde die Syntax der Erweiterungsmethoden mehr im Einklang mit dem Rest meines Codes. Ich mache meine SQL in SQL. Es ist auch sehr einfach, Ihren Ausdruck zu erstellen, indem Sie einfach alles mit den Erweiterungsmethoden hinzufügen.

Nur meine zwei Cent.

Da ich noch keine Kommentare abgeben kann, möchte ich hier eine Antwort auf die Antwort von Programming Tool machen: Warum eine ganz neue Methode für das letzte Beispiel machen? Kannst du nicht einfach benutzen:

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

14
Rodi

Sie kompilieren dasselbe und sind gleichwertig. Persönlich bevorzuge ich die Lambda-Methode (Erweiterung) für die meisten Dinge. Ich verwende nur die Anweisungen (Standard), wenn ich LINQ to SQL mache oder sonst versuche, SQL zu emulieren. Ich finde, dass die Lambda-Methoden mit Code besser fließen, während die Aussagen visuell ablenken.

6
Mark Brackett

Ich bevorzuge die Erweiterungsmethoden-Syntax, wenn ich Linq-Methoden verwende, die keine entsprechende Abfragesyntax haben, wie zum Beispiel FirstOrDefault () oder andere.

4
Eric Minkes

Ich benutze gerne die Abfragesyntax, wenn es sich wirklich um eine Abfrage handelt, dh um einen Lazy-Ausdruck, der bei Bedarf ausgewertet wird. 

Eine Methode, die wie reguläre Methodenaufrufe aussieht (Methodensyntax oder Lambda-Syntax), sieht nicht faul aus, daher verwende ich das als Konvention. Zum Beispiel

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

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

Wenn es sich nicht um eine Abfrage handelt, mag ich den fließenden Stil, der für mich im Einklang mit anderen eifrig ausgeführten Anrufen erscheint.

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

Es hilft mir, die zwei Arten von Anrufen besser zu unterscheiden. Natürlich gibt es Situationen, in denen Sie ohnehin gezwungen sein werden, Methodensyntax zu verwenden, daher ist meine Konvention nicht sehr überzeugend genug. 

0
nawfal