tuplas tupla informatica c# lambda tuples c#-7.0

c# - tuplas - tupla informatica



C#7 tuplas y lambdas (4)

Con la nueva sintaxis de tupla de c # 7, ¿es posible especificar una lambda con una tupla como parámetro y usar valores desempaquetados dentro de la lambda?

Ejemplo:

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

forma normal de usar una tupla en lambda:

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

esperaba un nuevo azúcar para evitar .Item1 .Item2 , como:

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

La última línea no funciona porque se trata como dos parámetros para lambda. No estoy seguro de si hay una manera de hacerlo realmente.

EDITAR:

Intenté doble parentesis en la definición lambda y no funcionó: ((x,y)) => ... , y tal vez fue estúpido intentarlo, pero el paréntesis doble realmente funciona aquí:

list.Add((1,2));

Además, mi pregunta no es sobre evitar los nombres predeterminados feos .Item .Item2 , se trata de desempacar una tupla en lambda (y tal vez por qué no está implementado o no es posible). Si vino aquí para encontrar una solución a los nombres predeterminados, lea la respuesta de Sergey Berezovskiy .

EDITAR 2:

Solo pensé en un caso de uso más general: ¿es posible (o por qué no) "deconstruir" la tupla pasada a un método? Me gusta esto:

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

En lugar de esto:

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


Como has observado, para:

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

Al menos uno esperaría poder hacer lo siguiente:

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

Pero el compilador C # 7 (todavía) no es compatible con esto. También es razonable desear azúcar que permita lo siguiente:

void Foo(int x, int y) => ... Foo(list[0]);

con el compilador que convierte Foo(list[0]); a Foo(list[0].Item1, list[0].Item2); automáticamente.

Ninguno de estos es actualmente posible. Sin embargo, el problema, Propuesta: deconstrucción de tuplas en la lista de argumentos lambda , existe en el repositorio dotnet/csharplang en GitHub, solicitando que el equipo de lenguaje considere estas características para una futura versión de C #. Agregue sus voces a ese hilo si a usted también le gustaría ver apoyo para esto.


Debe especificar los nombres de las propiedades de tupla (bueno, ValueTuple tiene campos) de lo contrario se usarán los nombres predeterminados, como ha visto:

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

Ahora las tuplas tienen campos bien nombrados que puedes usar

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

No olvides agregar el paquete System.ValueTuple de NuGet y tener en cuenta que ValueTuples son estructuras mutables.

Actualización: Deconstrucción actualmente representada solo como una asignación a variables existentes (asignación de deconstrucción) o a variables locales recién creadas (declaración de deconstrucción). El algoritmo de selección de miembro de función aplicable es el mismo que antes:

Cada argumento en la lista de argumentos corresponde a un parámetro en la declaración del miembro de la función como se describe en §7.5.1.1, y cualquier parámetro al que no corresponde ningún argumento es un parámetro opcional.

La variable tupla es un argumento único. No puede corresponder a varios parámetros en la lista de parámetros formales del método.


El programa con el que se está ejecutando es la incapacidad del compilador para inferir el tipo en esta expresión:

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

Pero dado que (int, int) y (int x, int y) son del mismo tipo CLR ( System.ValueType<int, int> ), si especifica los parámetros de tipo:

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

Funcionará.


Las deconstrucciones en C # 7.0 admiten tres formas:

  • declaración de deconstrucción (como (var x, var y) = e; ),
  • deconstrucción-asignación (como (x, y) = e; ),
  • y deconstrucción-foreach (como foreach(var(x, y) in e) ... ).

Se consideraron otros contextos, pero es probable que tengan una utilidad decreciente y no pudimos completarlos en el plazo de C # 7.0. La deconstrucción en una cláusula let ( let (x, y) = e ... ) y en lambdas parecen buenos candidatos para una futura expansión.

Este último se está discutiendo en https://github.com/dotnet/csharplang/issues/258

Exprese sus comentarios e intereses allí, ya que ayudará a defender las propuestas.

Más detalles sobre lo que se incluyó en la deconstrucción de C # 7.0 en el documento de diseño .