Fließender und fragender Ausdruck - Gibt es einen Vorteil gegenüber dem anderen?

255

LINQ ist eine der größten Verbesserungen von .NET seit Generika und spart mir jede Menge Zeit und Codezeilen. Die fließende Syntax scheint mir jedoch viel natürlicher zu sein als die Syntax des Abfrageausdrucks.

var title = entries.Where(e => e.Approved)
    .OrderBy(e => e.Rating).Select(e => e.Title)
    .FirstOrDefault();

var query = (from e in entries
             where e.Approved
             orderby e.Rating
             select e.Title).FirstOrDefault();

Gibt es einen Unterschied zwischen den beiden oder gibt es einen besonderen Vorteil von einem gegenüber dem anderen?

JarrettV
quelle
1
Bei komplexen Abfragen finde ich die Lambda-Syntax verständlicher / lesbarer, aber die Abfragesyntax ist einfach schöner.
Nawfal

Antworten:

255

Beides ist nicht besser: Sie dienen unterschiedlichen Bedürfnissen. Die Abfragesyntax kommt zur Geltung, wenn Sie mehrere Bereichsvariablen nutzen möchten . Dies geschieht in drei Situationen:

  • Bei Verwendung des Schlüsselworts let
  • Wenn Sie mehrere Generatoren haben ( aus Klauseln)
  • Beim Joins

Hier ist ein Beispiel (aus den LINQPad-Beispielen):

string[] fullNames = { "Anne Williams", "John Fred Smith", "Sue Green" };

var query =
  from fullName in fullNames
  from name in fullName.Split()
  orderby fullName, name
  select name + " came from " + fullName;

Vergleichen Sie dies nun mit der gleichen Methode in der Methodensyntax:

var query = fullNames
  .SelectMany (fName => fName.Split().Select (name => new { name, fName } ))
  .OrderBy (x => x.fName)
  .ThenBy  (x => x.name)
  .Select  (x => x.name + " came from " + x.fName);

Die Methodensyntax hingegen bietet die gesamte Bandbreite der Abfrageoperatoren und ist bei einfachen Abfragen präziser. Sie können das Beste aus beiden Welten herausholen, indem Sie die Abfrage- und Methodensyntax mischen. Dies geschieht häufig in LINQ to SQL-Abfragen:

var query =
  from c in db.Customers
  let totalSpend = c.Purchases.Sum (p => p.Price)    // Method syntax here
  where totalSpend > 1000
  from p in c.Purchases
  select new { p.Description, totalSpend, c.Address.State };
Joe Albahari
quelle
2
Gute Antwort. Können Sie mir etwas mehr darüber erzählen, was ".Select (name => new {name, fName})" tut?
Federbrecher
12
Es wählt das einzelne Wort (Anne, Williams, John usw.) zusammen mit dem vollständigen Namen in einem anonymen Typ aus. Auf diese Weise können Sie den ursprünglichen vollständigen Namen "tragen", sodass Sie im Rest der Abfrage sowohl auf den vollständigen Namen als auch auf das einzelne Wort zugreifen können.
Joe Albahari
58

Ich bevorzuge die Verwendung der letzteren (manchmal als "Abfrageverständnis-Syntax" bezeichnet), wenn ich den gesamten Ausdruck auf diese Weise schreiben kann.

var titlesQuery = from e in entries
                  where e.Approved
                  orderby e.Rating
                  select e.Titles;

var title = titlesQuery.FirstOrDefault();

Sobald ich (Klammern) und hinzufügen muss .MethodCalls(), ändere ich.

Wenn ich die erstere verwende, setze ich normalerweise eine Klausel pro Zeile wie folgt:

var title = entries
    .Where (e => e.Approved)
    .OrderBy (e => e.Rating)
    .Select (e => e.Title)
    .FirstOrDefault();

Ich finde das etwas leichter zu lesen.

Jay Bazuzi
quelle
29

Jeder Stil hat seine Vor- und Nachteile. Die Abfragesyntax ist bei Verknüpfungen besser und verfügt über das nützliche Schlüsselwort let , mit dem das Erstellen temporärer Variablen in einer Abfrage vereinfacht wird.

Fließende Syntax hingegen bietet viel mehr Methoden und Operationen, die durch die Abfragesyntax nicht verfügbar gemacht werden. Da es sich nur um Erweiterungsmethoden handelt, können Sie auch Ihre eigenen schreiben.

Ich habe festgestellt, dass ich jedes Mal, wenn ich mit dem Schreiben einer LINQ-Anweisung unter Verwendung der Abfragesyntax beginne, diese in Klammern setzen und auf fließende LINQ-Erweiterungsmethoden zurückgreifen muss. Die Abfragesyntax verfügt einfach nicht über genügend Funktionen, um sie selbst zu verwenden.

James Newton-King
quelle
"Da es sich nur um Erweiterungsmethoden handelt, können Sie Ihre eigenen schreiben." - Würden Sie auf dieses Problem stoßen? stackoverflow.com/a/3850254/1175496
Die rote Erbse
20

In VB.NET bevorzuge ich die Abfragesyntax.

Ich hasse es, das hässliche FunctionSchlüsselwort zu wiederholen :

Dim fullNames = { "Anne Williams", "John Fred Smith", "Sue Green" };
Dim query =
     fullNames.SelectMany(Function(fName) fName.Split().
     Select(Function(Name) New With {Name, fName})).
     OrderBy(Function(x) x.fName).
     ThenBy(Function(x) x.Name).
     Select(Function(x) x.Name & " came from " & x.fName)

Diese nette Abfrage ist meiner Meinung nach viel besser lesbar und wartbar:

query = From fullName In fullNames
        From name In fullName.Split()
        Order By fullName, name
        Select name & " came from " & fullName

Die Abfragesyntax von VB.NET ist außerdem leistungsfähiger und weniger ausführlich als in C #: https://stackoverflow.com/a/6515130/284240

Zum Beispiel diese LINQ to DataSet-Abfrage (Objekte)

VB.NET:

Dim first10Rows = From r In dataTable1 Take 10

C #:

var first10Rows = (from r in dataTable1.AsEnumerable() 
                   select r)
                   .Take(10);
Tim Schmelter
quelle
9
Mein Mitgefühl für diejenigen VB-Entwickler, die den Abfragestil nicht verwenden können.
Nawfal
1
Ihr letztes C # -Beispiel ist zu simpel, um wertvoll zu sein: Sie würden einfach `dataTable1.AsEnumerable () schreiben. Take (10);
Emyr
@Emyr: Mein letzter Absatz, der mit "Die Abfragesyntax von VB.NET ist ebenfalls leistungsfähiger und weniger ausführlich als in C #" beginnt, vergleicht nur die Abfragesyntax von VB.NET mit C #. Sie verwenden die Methodensyntax.
Tim Schmelter
15

Ich verstehe die Abfragesyntax überhaupt nicht. Ich habe einfach keinen Grund dafür. let kann mit .Select und anonymen Typen erreicht werden. Ich denke nur, dass die Dinge mit der "Interpunktion" dort viel organisierter aussehen.

Instanzjäger
quelle
9
Mehrere Verknüpfungen können mit der fließenden Syntax sehr schnell sehr mühsam werden. Im Allgemeinen spreche ich selbst fließend - es sei denn, es handelt sich um Joins.
Roman Starkov
1
@ Instance Hunter: Gleich hier. Ich habe eine ganze Weile gebraucht, um die Idee einer fließenden Syntax zu verstehen. In Kombination mit der leistungsstarken Aufzählung und der Idee von "reinen" Funktionen macht es mir jetzt wirklich Spaß, und früher knifflige Situationen, in denen es keine schöne Codedarstellung gab. Für den alten SQL-Teil des Gehirns ist es immer noch ein Segen, eine Abfragesyntax zu haben.
Xan-Kun Clark-Davis
13

Die fließende Schnittstelle, wenn es nur ein Wo gibt. Wenn ich eine Auswahl oder Bestellung benötige, verwende ich im Allgemeinen die Abfragesyntax.

James Curran
quelle
8

Fließende Syntax scheint in der Tat leistungsfähiger zu sein. Sie sollte auch besser für die Organisation von Code in kleinen wiederverwendbaren Methoden funktionieren.

Kozyarchuk
quelle
5

Ich weiß, dass diese Frage mit C # gekennzeichnet ist, aber die Fluent-Syntax ist mit VB.NET schmerzhaft ausführlich.

Larsenal
quelle
4

Ich mag die Fluent-Syntax sehr und versuche, sie zu verwenden, wo ich kann, aber in bestimmten Fällen, zum Beispiel wenn ich Joins verwende, bevorzuge ich normalerweise die Abfragesyntax. In diesen Fällen finde ich es einfacher zu lesen, und ich denke, einige Leute kennen die SQL-ähnliche Abfragesyntax besser als Lambdas.

CMS
quelle
4

Obwohl ich das fließende Format verstehe und mag, habe ich mich aus Gründen der Lesbarkeit vorerst an Query gehalten. Personen, die gerade mit LINQ vertraut gemacht werden, finden es viel angenehmer, Query zu lesen.

LizB
quelle
4

Ich bevorzuge die Abfragesyntax, da ich aus der traditionellen Webprogrammierung mit SQL stamme. Es ist viel einfacher für mich, meinen Kopf herumzuwickeln. Ich denke jedoch, dass ich anfangen werde, das .Where (Lambda) zu verwenden, da es definitiv viel kürzer ist.

Steve Tranby
quelle
4

Ich benutze Linq jetzt seit ungefähr 6 Monaten. Als ich anfing, es zu verwenden, bevorzugte ich die Abfragesyntax, da sie T-SQL sehr ähnlich ist.

Aber ich komme jetzt allmählich zu ersteren, da es einfach ist, wiederverwendbare Codestücke als Erweiterungsmethoden zu schreiben und sie einfach miteinander zu verketten. Obwohl ich finde, dass es sehr hilfreich ist, jede Klausel in eine eigene Zeile zu setzen.

Antony Scott
quelle
3

Ich habe gerade die Standards unseres Unternehmens festgelegt und wir erzwingen die Verwendung der Erweiterungsmethoden. Ich denke, es ist eine gute Idee, eine über die andere zu wählen und sie nicht im Code zu verwechseln. Erweiterungsmethoden lesen sich eher wie der andere Code.

Die Verständnissyntax enthält nicht alle Operatoren und verwendet Klammern um die Abfrage und fügt Erweiterungsmethoden hinzu, schließlich bittet mich nur, von Anfang an Erweiterungsmethoden zu verwenden.

Aber zum größten Teil ist es nur eine persönliche Präferenz mit wenigen Ausnahmen.

Rodi
quelle
3
Ich werde keine persönlichen Vorlieben durchsetzen. Aber das bin ich.
Memet Olsen