web-dev-qa-db-fra.com

Méthodes d'extension syntaxe vs syntaxe de requête

J'essaie de savoir s'il est temps d'utiliser les mots-clés linq standard ou les méthodes d'extension linq avec des expressions lambda. Ils semblent faire la même chose, ils sont simplement écrits différemment. Est-ce purement une question de style?

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

Ils sont très similaires, le deuxième exemple étant un peu plus concis, mais peut-être moins expressif si vous ne savez pas ce que fait =>.

Outre l'écriture de code laconique, l'utilisation des méthodes d'extension présente-t-elle d'autres avantages que la syntaxe LINQ?

63
Armstrongest

Honnêtement, cela peut parfois être situationnel une fois que vous commencez à utiliser Funcs et Actions. Disons que vous utilisez ces trois fonctions:

  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;

Comme vous pouvez le voir, le premier remplace l'expression lamdba pour obtenir le nom d'utilisateur, le second remplace une expression lamdba utilisée pour vérifier si l'ID est inférieur à 10, et avouons-le, le troisième devrait être assez facile à comprendre maintenant.

Remarque: il s'agit d'un exemple stupide, mais cela fonctionne.

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

Versus

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

Dans cet exemple, le second est un peu moins détaillé puisque la méthode d'extension peut utiliser pleinement le Func, mais l'expression Linq ne le peut pas, car il s'agit uniquement d'un booléen plutôt que d'un Func renvoyant un booléen. Cependant, il serait peut-être préférable d’utiliser le langage d’expression. Supposons que vous ayez déjà une méthode qui englobe plus qu'un utilisateur:

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

Remarque: doSomething existe uniquement en raison de l’extension de la méthode d’extension where avec une méthode qui prend un utilisateur et un entier et renvoie un booléen. Un peu gênant pour cet exemple.

Maintenant, si vous regardez la requête Linq:

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

Tu es bon pour ça. Maintenant la méthode d'extension:

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

Sans expression lambda, je ne peux vraiment pas appeler cette méthode. Alors maintenant, ce que je dois faire, c'est créer une méthode qui crée un Func basé sur l'appel de la méthode d'origine.

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

Et puis branchez-le:

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

Comme vous pouvez le constater, il est parfois parfois plus simple d’utiliser la méthode de la requête.

33
Programmin Tool

L’un des avantages de l’utilisation des méthodes d’extension LINQ (requêtes sur les méthodes ) est que vous pouvez définir des méthodes d’extension personnalisées et que la lecture est correcte.

En revanche, lorsque vous utilisez une expression LINQ query, la méthode d'extension personnalisée ne figure pas dans la liste de mots-clés. Cela aura l'air un peu étrange mélangé avec les autres mots-clés. 

Exemple

J'utilise une méthode d'extension personnalisée appelée Into qui prend simplement une chaîne:

Exemple avec requête

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

Exemple avec des méthodes d'extension

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

À mon avis, ce dernier, utilisant une requête basée sur method, se lit mieux lorsque vous avez des méthodes d'extension personnalisées.

24
Nathan W

Je pense que c'est une bonne idée de ne pas les utiliser ensemble, en choisir un et s'en tenir à cela.

Généralement, il s'agit d'un goût personnel, mais dans la syntaxe de la requête (méthode de compréhension), tous les opérateurs ne sont pas disponibles comme cela a été dit auparavant.

Je trouve la syntaxe d'Extension Methods plus en ligne avec le reste de mon code. Je fais mon SQL en SQL. Il est également très facile de construire votre expression simplement en ajoutant tout ce qui s’y superpose avec les méthodes d’extension.

Juste mes deux cents.

Comme je ne peux pas encore faire de commentaires, je voudrais en faire un ici à la réponse de Programming Tool: Pourquoi créer une toute nouvelle méthode pour le dernier exemple? Ne pouvez-vous pas simplement utiliser:

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

14
Rodi

Ils compilent le même, et sont équivalents. Personnellement, je préfère les méthodes lambda (extension) pour la plupart des choses, en n'utilisant que les instructions (standard) si je fais LINQ to SQL ou si j'essaie d'émuler SQL. Je trouve que les méthodes lambda sont plus fluides avec le code, alors que les énoncés sont distrayants visuellement.

6
Mark Brackett

Je préfère la syntaxe de méthode d'extension lorsque j'utilise des méthodes Linq qui n'ont pas d'équivalent de requête, tel que FirstOrDefault () ou d'autres méthodes similaires.

4
Eric Minkes

J'aime utiliser la syntaxe de requête lorsque c'est vraiment une requête, c'est-à-dire une expression lazy qui évalue à la demande. 

Une méthode qui ressemble à des appels de méthode normaux (syntaxe de méthode ou lambda) ne semble pas assez fainéante, donc je l'utilise comme convention. Pour, par exemple,

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

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

Si ce n'est pas une requête, j'aime le style fluide qui me semble cohérent avec les autres appels en cours d'exécution.

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

Cela m'aide à mieux différencier les deux styles d'appels. Bien sûr, il y a des situations dans lesquelles vous serez forcé d'utiliser la syntaxe de la méthode, donc ma convention n'est pas très convaincante. 

0
nawfal