web-dev-qa-db-fra.com

LINQ - Syntaxe de requête vs chaînes de méthodes et lambda

Quelqu'un s'en tient-il à des règles (ou êtes-vous obligé de vous en tenir à des règles de votre employeur?) Lorsque vous choisissez d'utiliser la syntaxe de requête LINQ ou une expression Lambda dans l'une des méthodes d'extension LINQ? Cela s'applique à toutes les entités, SQL, objets, quoi que ce soit.

Sur notre lieu de travail, mon patron n'aime pas du tout lambda et il utiliserait la syntaxe de requête pour tout ce qui, dans certains cas, je trouve qu'ils sont moins lisibles.

var names = collection.Select(item => item.Name);

var names = from item in collection
            select item.Name;

Peut-être que lors de l'ajout d'une condition, la Lambda que je trouve devient un peu désordonnée, où la

var names = collection.Where(item => item.Name == "Fred")
                      .Select(item => item.Name);

var names = from item in collection
            where item.Name == "Fred"
            select item.Name;

Juste par intérêt: comment le compilateur traite-t-il celui-ci? Quelqu'un sait-il comment la requête LINQ ci-dessus se compilera dans lambda? La propriété Name sera-t-elle appelée pour chaque élément? Pourrions-nous le faire à la place et potentiellement améliorer les performances? Cela signifierait-il que lambda est légèrement plus contrôlable en termes de performances?

var names = collection.Select(item => item.Name)
                      .Where(name => name == "Fred");

Certes, lorsque nous commençons à utiliser de plus en plus d'expressions, le lambda devient désordonné et je commencerais à utiliser la syntaxe de requête ici.

var names = collection.Where(item => item.Name == "Fred")
                      .OrderBy(item => item.Age)
                      .Select(item => item.Name);

var names = from item in collection
            where item.Name == "Fred"
            order by item.Age
            select item.Name;

Il y a aussi quelques choses que je ne peux pas faire avec la syntaxe de requête. Vous penseriez que certaines d'entre elles seraient vraiment simples (en particulier les fonctions d'agrégation), mais non, vous devez ajouter une des méthodes d'extension LINQ à la fin, qui, imo, semble plus nette avec une expression lambda.

var names = collection.Count(item => item.Name == "Fred");

var names = (from item in collection
            where item.Name == "Fred"
            select item).Count()

Même pour certaines des chaînes lambda simples, ReSharper suggère de les convertir en requêtes LINQ.

Quelqu'un d'autre peut-il ajouter à cela? Quelqu'un a-t-il ses propres règles ou son entreprise suggère-t-elle/force-t-elle d'en utiliser une?

53
Connell

Pour répondre à votre question sur la traduction, l'expression de requête sera toujours traduite selon les règles de 7.16 de la spécification C # 4 (ou l'équivalent dans la spécification C # 3). Dans l'exemple où vous posez la question sur la propriété Name, ce n'est pas une question de traduction d'expression de requête - c'est ce que les méthodes Select et Where font avec la délégués ou arborescences d'expression qu'ils prennent comme paramètres. Parfois, il est logique de faire une projection avant de filtrer, parfois non.

Quant aux petites règles, je n'en ai qu'une: utilisez la méthode la plus lisible pour la requête en question. Donc, si la requête change et "quelle forme est plus lisible" change en même temps, changez la syntaxe utilisée.

Si vous allez utiliser LINQ, vous devriez être satisfait de l'une ou l'autre syntaxe, à tout le moins lire.

I tendance pour trouver que les requêtes avec plusieurs variables de plage (par exemple via SelectMany ou Join, ou une clause let) finissent par être plus lisibles en utilisant expressions de requête - mais c'est loin d'être une règle stricte et rapide.

35
Jon Skeet