C # 7 tuplas y lambdas
Con la nueva sintaxis de la tupla de c# 7, ¿es posible especificar una lambda con una tupla como parámetro y usar valores descomprimidos 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 poco de azúcar nuevo para evitar .Item1
.Item2
, me gusta:
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 realidad.
EDITAR:
Probé el doble la parentesis en la definición lambda y no funcionó: ((x,y)) => ...
, y tal vez fue estúpido intentarlo, pero el doble paréntesis realmente funciona aquí:
list.Add((1,2));
Además, mi pregunta no es acerca de evitar nombres por defecto feos .Item .Item2
, se trata de desempaquetar una tupla en lambda (y tal vez por qué no se implementa o no es posible). Si ha venido aquí para encontrar una solución a los nombres predeterminados, lea La respuesta de Sergey Berezovskiy.
EDITAR 2:
Acabo de pensar en un caso de uso más general: ¿es posible (o por qué no) "deconstruir" la tupla pasada a un método? Así:
void Foo((int,int)(x,y)) { x+y; }
En lugar de esto:
void Foo((int x,int y) value) { value.x+value.y }
4 answers
Como usted ha 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 de C# 7 (todavía) no soporta esto. También es razonable desear azúcar que permita lo siguiente:
void Foo(int x, int y) => ...
Foo(list[0]);
Con el compilador convirtiendo Foo(list[0]);
a Foo(list[0].Item1, list[0].Item2);
automáticamente.
Ninguna de ellas es posible actualmente. 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 versión futura de C#. Por favor, agregue sus voces a ese hilo si también desea ver soporte para esto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-29 09:31:29
Debe especificar los nombres de las propiedades de la tupla (bueno, ValueTuple tiene campos) de lo contrario se usarán nombres predeterminados, como ha visto:
var list = new List<(int x, int y)>();
Ahora la tupla tiene campos bien nombrados que puede usar
list.Select(t => t.x * 2 + t.y / 2)
No olvides agregar Sistema.ValueTuple paquete de NuGet y tenga en cuenta que los ValueTuples son estructuras mutables.
Actualización: La deconstrucción se representa actualmente solo como una asignación a variables existentes (deconstructon-assignment) o a variables locales creadas (deconstrucción-declaración). El algoritmo de selección de miembros de la 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 corresponda ningún argumento es un parámetro opcional.
La variable Tupla es un único argumento. No puede corresponder a varios parámetros en la lista formal de parámetros del método.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-29 03:35:04
Las deconstrucciones en C# 7.0 admiten tres formas:
- deconstrucción-declaració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 probablemente tienen una utilidad decreciente y no pudimos completarlos en el marco temporal 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 .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-08 21:24:22
El programa en el que se encuentra 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 el 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á.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-29 06:54:15