Expression courante et requête - Y a-t-il des avantages l'un par rapport à l'autre?

255

LINQ est l'une des plus grandes améliorations de .NET depuis les génériques et il me fait gagner des tonnes de temps et des lignes de code. Cependant, la syntaxe courante me semble beaucoup plus naturelle que la syntaxe d'expression de requête.

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

Y a-t-il une différence entre les deux ou y a-t-il un avantage particulier l'un par rapport à l'autre?

JarrettV
la source
1
Pour les requêtes complexes, je trouve la syntaxe lambda plus compréhensible / lisible, mais la syntaxe de requête est tout simplement plus jolie.
nawfal

Réponses:

255

Ni mieux, ils répondent à des besoins différents. La syntaxe de requête prend tout son sens lorsque vous souhaitez exploiter plusieurs variables de plage . Cela se produit dans trois situations:

  • Lors de l'utilisation du mot clé let
  • Lorsque vous avez plusieurs générateurs (à partir de clauses)
  • Lors de jointures

Voici un exemple (à partir des exemples LINQPad):

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;

Comparez maintenant cela à la même chose dans la syntaxe de la méthode:

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

La syntaxe de la méthode, d'autre part, expose la gamme complète des opérateurs de requête et est plus concise avec les requêtes simples. Vous pouvez tirer le meilleur parti des deux mondes en mélangeant la syntaxe des requêtes et des méthodes. Cela se fait souvent dans les requêtes LINQ to SQL:

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
la source
2
Bonne réponse. Pouvez-vous m'en dire un peu plus sur ce que fait ".Select (name => new {name, fName})"?
briseur de plume
12
Il sélectionne le mot individuel (anne, williams, john, etc.) ainsi que le nom complet dans un type anonyme. Cela vous permet de «porter» le nom complet d'origine afin d'avoir accès à la fois au nom complet et au mot individuel dans le reste de la requête.
Joe Albahari
58

Je préfère utiliser cette dernière (parfois appelée "syntaxe de compréhension des requêtes") quand je peux écrire l'expression entière de cette façon.

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

var title = titlesQuery.FirstOrDefault();

Dès que je dois ajouter (parenthèses) et .MethodCalls(), je change.

Lorsque j'utilise le premier, je mets généralement une clause par ligne, comme ceci:

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

Je trouve cela un peu plus facile à lire.

Jay Bazuzi
la source
29

Chaque style a ses avantages et ses inconvénients. La syntaxe de requête est plus agréable en ce qui concerne les jointures et elle a le mot-clé let utile qui facilite la création de variables temporaires dans une requête.

La syntaxe courante, d'autre part, a beaucoup plus de méthodes et d'opérations qui ne sont pas exposées via la syntaxe de requête. De plus, comme ce ne sont que des méthodes d'extension, vous pouvez écrire les vôtres.

J'ai constaté que chaque fois que je commence à écrire une instruction LINQ à l'aide de la syntaxe de requête, je finis par la mettre entre parenthèses et à recourir à des méthodes d'extension LINQ fluides. La syntaxe de requête n'a tout simplement pas assez de fonctionnalités à utiliser seule.

James Newton-King
la source
"car ce ne sont que des méthodes d'extension, vous pouvez écrire les vôtres." - Souhaitez-vous rencontrer ce problème? stackoverflow.com/a/3850254/1175496
The Red Pea
20

Dans VB.NET, je préfère de beaucoup la syntaxe des requêtes.

Je déteste répéter le vilain Functionmot-clé:

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)

Cette requête soignée est beaucoup plus lisible et maintenable à mon avis:

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

La syntaxe de requête de VB.NET est également plus puissante et moins verbeuse qu'en C #: https://stackoverflow.com/a/6515130/284240

Par exemple, cette requête LINQ to DataSet (Objects)

VB.NET:

Dim first10Rows = From r In dataTable1 Take 10

C #:

var first10Rows = (from r in dataTable1.AsEnumerable() 
                   select r)
                   .Take(10);
Tim Schmelter
la source
9
Mes sympathies pour les développeurs VB qui ne peuvent pas utiliser le style de requête.
nawfal
1
Votre dernier exemple C # est trop simpliste pour être utile: vous écririez simplement `dataTable1.AsEnumerable (). Take (10);
Emyr
@Emyr: mon dernier paragraphe qui commence par "La syntaxe de requête de VB.NET est également plus puissant et moins verbeux qu'en C #" compare simplement la syntaxe de requête de VB.NET avec C #, vous utilisez la syntaxe de méthode.
Tim Schmelter
15

Je ne reçois pas du tout la syntaxe de la requête. Il n'y a simplement aucune raison à cela dans mon esprit. let peut être obtenu avec les types .Select et anonymes. Je pense juste que les choses semblent beaucoup plus organisées avec la "ponctuation" là-dedans.

Chasseur d'instances
la source
9
Les jointures multiples peuvent devenir assez laborieuses assez rapidement avec la syntaxe fluide. Cependant, j'utilise généralement couramment moi-même - sauf si des jointures sont impliquées.
Roman Starkov
1
@Instance Hunter: Même chose ici. Il m'a fallu un certain temps pour commencer à saisir l'idée d'une syntaxe fluide. En combinaison avec l'énumérable puissant et l'idée de fonctions "pures", je l'apprécie maintenant vraiment, et les situations auparavant délicates qui n'avaient pas de belle représentation de code. Pour la partie ye-ole-SQL du cerveau, c'est toujours une chance d'avoir une syntaxe de requête.
Xan-Kun Clark-Davis
13

L'interface fluide s'il n'y a qu'un endroit. Si j'ai besoin d'une sélection ou d'une commande, j'utilise généralement la syntaxe de requête.

James Curran
la source
8

La syntaxe courante semble effectivement plus puissante, elle devrait également fonctionner mieux pour organiser le code en petites méthodes réutilisables.

Kozyarchuk
la source
5

Je sais que cette question est balisée avec C #, mais la syntaxe Fluent est douloureusement verbeuse avec VB.NET.

Larsenal
la source
4

J'aime vraiment la syntaxe Fluent et j'essaie de l'utiliser où je peux, mais dans certains cas, par exemple lorsque j'utilise des jointures, je préfère généralement la syntaxe Query, dans ces cas, je la trouve plus facile à lire, et je pense que certaines personnes sont plus familiers avec la syntaxe Query (de type SQL) que les lambdas.

CMS
la source
4

Bien que je comprenne et que j'aime le format fluide, je suis resté fidèle à Query pour le moment pour des raisons de lisibilité. Les personnes qui viennent de découvrir LINQ trouveront Query beaucoup plus confortable à lire.

LizB
la source
4

Je préfère la syntaxe de requête car je viens de la programmation Web traditionnelle utilisant SQL. Il est beaucoup plus facile pour moi d'envelopper ma tête. Cependant, il pense que je vais commencer à utiliser le .Where (lambda) car il est certainement beaucoup plus court.

Steve Tranby
la source
4

J'utilise Linq depuis environ 6 mois maintenant. Lorsque j'ai commencé à l'utiliser, j'ai préféré la syntaxe de requête car elle est très similaire à T-SQL.

Mais, je reviens progressivement à l'ancien, car il est facile d'écrire des morceaux de code réutilisables en tant que méthodes d'extension et de les enchaîner. Bien que je trouve que mettre chaque clause sur sa propre ligne aide beaucoup à la lisibilité.

Antony Scott
la source
3

Je viens de mettre en place les normes de notre entreprise et nous imposons l'utilisation des méthodes d'extension. Je pense que c'est une bonne idée de choisir l'un plutôt que l'autre et de ne pas les mélanger dans le code. Les méthodes d'extension ressemblent davantage à l'autre code.

La syntaxe de compréhension n'a pas tous les opérateurs et l'utilisation de parenthèses autour de la requête et ajoute des méthodes d'extension après tout, me supplie d'utiliser les méthodes d'extension depuis le début.

Mais pour la plupart, c'est juste une préférence personnelle à quelques exceptions près.

Rodi
la source
3
Je n'appliquerai pas les préférences personnelles .. Mais c'est moi.
Memet Olsen