93 votes

Tuples et lambdas C # 7

Avec c# 7 tuple de la syntaxe, est-il possible de spécifier un lambda avec un tuple comme paramètre et utilisez déballé valeurs à l'intérieur de la lambda?

Exemple:

var list = new List<(int,int)>();

normal pour utiliser un tuple dans lambda:

list.Select(value => value.Item1*2 + value.Item2/2);

j'ai attendu quelques nouvelles de sucre pour éviter .Item1 .Item2, comme:

list.Select((x,y) => x*2 + y/2);

La dernière ligne ne fonctionne pas car il est traité comme deux paramètres pour lambda. Je ne suis pas sûr si il ya un moyen de le faire réellement.

EDIT:

J'ai essayé le double parentesis en lambda définition et ça ne fonctionne pas: ((x,y)) => ..., et c'était peut-être stupide pour essayer, mais la double parenthèse effectivement le travail ici:

list.Add((1,2));

Aussi, ma question n'est pas tout à fait à propos en évitant laid noms par défaut .Item .Item2, c'est un réel déballage d'un tuple dans lambda (et peut-être pourquoi il n'est pas mis en œuvre ou non possible). Si vous êtes venu ici pour une solution à défaut, les noms, lire Sergey Berezovskiy de réponse.

EDIT 2:

Juste la pensée d'une manière plus générale: est-il possible (ou pourquoi pas), pour "démolir" n-uplet passés à une méthode? Comme ceci:

void Foo((int,int)(x,y)) { x+y; }

Au lieu de cela:

void Foo((int x,int y) value) { value.x+value.y }

68voto

David Arno Points 15499

Comme vous l'avez observé, pour:

var list = new List<(int,int)>();

On pourrait au moins s'attendre à être en mesure de faire ce qui suit:

list.Select((x,y) => x*2 + y/2);

Mais le C# 7 compilateur n'a pas (encore) cette fonction en charge. Il est également raisonnable de désir de sucre, qui permettrait à la suivante:

void Foo(int x, int y) => ...

Foo(list[0]);

avec le compilateur de conversion Foo(list[0]); de Foo(list[0].Item1, list[0].Item2); automatiquement.

Aucune de ces options n'est possible actuellement. Toutefois, la question, Proposition: Tuple de la déconstruction dans le lambda de la liste d'arguments, il existe sur l' dotnet/csharplang repo GitHub, demandant à ce que la langue de l'équipe de tenir compte de ces caractéristiques pour une future version de C#. Veuillez ajouter votre voix à ce thread si vous aussi vous voulez voir le support pour cela.

49voto

Sergey Berezovskiy Points 102044

Vous devez spécifier des noms de n-uplet propriétés (bien, ValueTuple ont des champs) sinon noms par défaut sera utilisé, comme vous l'avez vu:

var list = new List<(int x, int y)>();

Maintenant tuple ont gentiment nom des champs que vous pouvez utiliser

list.Select(t => t.x * 2 + t.y / 2)

N'oubliez pas d'ajouter le Système.ValueTuple paquet de NuGet et de garder à l'esprit que ValueTuples sont mutables des structures.


Mise à jour: Déconstruction actuellement représentée comme une affectation de variables existantes (deconstructon-affectation) ou nouvellement créés variables locales (déconstruction-déclaration). Applicable en fonction de membre de l'algorithme de sélection est le même que précédemment:

Chaque argument en argument la liste correspond à un paramètre dans la fonction de membre de déclaration telle que décrite dans le §7.5.1.1, et un paramètre à laquelle aucun argument correspond est un paramètre facultatif.

N-uplet de variables est un seul argument. Il ne peut pas correspondre à plusieurs paramètres dans la liste de paramètres formels de la méthode.

17voto

Julien Couvreur Points 76

Installations en C# 7.0 soutenir trois formes:

  • déconstruction-déclaration (comme (var x, var y) = e;),
  • la déconstruction de cession (comme (x, y) = e;),
  • et de la déconstruction-foreach (comme foreach(var(x, y) in e) ...).

D'autres contextes ont été envisagées, mais probablement la diminution de l'utilitaire et nous ne pouvions pas terminer dans le C# 7.0 calendrier. La déconstruction dans une clause let (let (x, y) = e ...) et dans les lambdas semblent de bons candidats pour une expansion future.

Ce dernier est en cours de discussion dans https://github.com/dotnet/csharplang/issues/258

Vocal vos commentaires et de votre intérêt, car cela aidera champion propositions.

Plus de détails sur ce qui a été inclus dans C# 7.0 déconstruction dans la conception doc.

13voto

Paulo Morgado Points 1015

Le programme que vous exécutez est l'incapacité du compilateur à déduire le type dans cette expression:

 list.Select(((int x, int y) t) => t.x * 2 + t.y / 2);
 

Mais puisque (int, int) et (int x, int y) sont du même type CLR ( System.ValueType<int, int> ), si vous spécifiez les paramètres de type:

 list.Select<(int x, int y), int>(t => t.x * 2 + t.y / 2);
 

Ça va marcher.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X