Style C #: Lambdas, _ => ou x =>?

J’ai utilisé les expressions lambda dans d’autres langues avant de les utiliser en C #, et j’ai donc pris l’habitude d’utiliser _ pour les lambdas simples sous la forme de Func, particulier pour les lambdas simples où le corps n’est qu’une expression. représentant la valeur de retour (prédicats, etc.). Cependant, en C #, je vois souvent des lettres simples utilisées à la place de _ pour ces mêmes types d’expressions lambda, telles que x,y,z,i,j,k . L’approche par les lettres me semble étrange, car ces lettres ont déjà une autre signification typique dans l’utilisation courante, pour les variables de boucle. _ est souvent plus facile à lire à mon avis. Le style à lettre unique est-il vraiment le style établi pour les lambdas en C #?

Exemples:

ce que j’ai l’habitude d’écrire:

 var ages = people.Select(_ => _.Age); 

Ce que je vois être écrit à la place:

 var ages = people.Select(x => x.Age); // choice of 'x' is not consistent 

De nombreux développeurs C # utilisent _ pour indiquer que le paramètre ne sera pas utilisé et une lettre ou un autre nom abrégé lorsque le paramètre est utilisé.

Autres ressources:

  • Discussion intéressante sur l’utilisation de _ au lieu de ()

C’est un nom de variable, donc j’y vais avec l’idée que le nom devrait transmettre les informations qu’il doit transmettre. Quelles informations _ transmet-on?

Dans le même but, quelles informations x transmet-il?

Je pourrais écrire votre exemple comme ceci:

 var ages = people.Select(p => p.Age); 

L’idée est que je pense que le p suggère au moins, dans le contexte de la déclaration entière, qu’il s’agit d’un record people . Vous pouvez aller encore plus loin:

 var ages = people.Select(person => person.Age); 

Maintenant, cela indique au lecteur quelle est cette variable. Bien sûr, pour une déclaration aussi petite, on peut argumenter que c’est exagéré. Je ne pense pas, mais c’est une question de préférence. (Et pas seulement votre préférence, mais la préférence de quiconque doit supporter ce code.)

Pour des expressions lambda complexes, multilignes et considérablement plus grandes, le nom devient encore plus important. Plus on s’éloigne du contexte de la signification de la variable, plus le nom de la variable doit être associé à ce contexte.

En quoi une fonction lambda est-elle si différente de toute autre méthode? Si quelqu’un devait poster du code avec une méthode telle que:

 public static int getAge(Person _) { return _.Age; } 

ou

 public static int getAge(Person x) { return x.Age; } 

Que dirais-tu?

À mon avis, choisir le nom d’un paramètre pour un lambda devrait être tout aussi significatif que le paramètre de toute autre méthode. Je peux faire des exceptions occasionnelles pour une fonction d’identité x => x car dans ce cas, la variable n’a pas besoin de signifier quoi que ce soit, elle peut en réalité être n’importe quoi, mais utiliser un trait de soulignement ou une lettre pour tout dans mon esprit crée simplement le code beaucoup moins lisible. (Tant de gens vantent les avantages de LINQ / Lambdas comme étant la lisibilité, ce qui est vaincu si vous masquez toutes les variables.)

Ou vous pouvez utiliser un nom significatif, par exemple

 var ages = people.Select(person => person.Age); 

En C #, _ est utilisé pour les variables de classe (atsortingbut) et _ n’est pas utilisé pour les variables locales. Il est donc bon d’utiliser un nom significatif pour les variables locales et les variables de classe.

Ex:

 var personList = (from person in people where person.Age > 18 select person).ToList(); 

Il n’y a pas de style “établi” pour nommer vos variables lambda. Toutefois, un trait de soulignement signifie généralement une sorte de variable membre d’instance, ce qui signifie que votre style peut entrer en conflit avec d’autres normes de dénomination que le nom d’une variable normale.

Long Story Short – Faites ce qui vous convient.

Il y a une raison pour laquelle vous pouvez lui donner un nom – parce que vous pouvez parfois avoir plusieurs entrées et avoir besoin de les différencier:

 Func product = (num1, num2) => (num1 * num2); // takes in two ints, and returns one int int x = product(2, 3);