CodeGym /Cursos /C# SELF /Nombrar elementos y deconstrucción de tuplas

Nombrar elementos y deconstrucción de tuplas

C# SELF
Nivel 11 , Lección 2
Disponible

1. Nombrar tuplas: contexto para la deconstrucción

En la lección anterior ya vimos los elementos nombrados de las tuplas, que permiten que el código sea mucho más legible, accediendo a los valores no por los impersonales Item1, Item2, sino por nombres con sentido (por ejemplo, person.Name). Esta posibilidad de poner nombres a los elementos de la tupla es especialmente importante cuando se usan como valores de retorno de métodos, parámetros o propiedades. Justo el nombrado es la clave para una deconstrucción cómoda, que vamos a ver más adelante en esta lección.

Recuerda, los nombres se pueden poner al inicializar la tupla con un literal, y también en la firma del valor de retorno de un método, propiedad o campo.

Ejemplo con método: Elementos nombrados de tupla en el valor de retorno de un método


public static (int Edad, string Nombre) GetPetInfo()
{
    return (Edad: 5, Nombre: "Fluffy");
}

// Uso:
var info = GetPetInfo();
Console.WriteLine($"{info.Nombre} — {info.Edad} años");

Ejemplo con campo/propiedad: Elementos nombrados de tupla en un campo/propiedad


public (int Ancho, int Alto) ImageSize = (1024, 768);

Recuerda: si no pones nombres explícitamente, los elementos seguirán estando accesibles por Item1, Item2 y así. Esto puede hacer el código menos legible, sobre todo si usas la tupla más adelante. Por eso se recomienda siempre poner nombres con sentido a los elementos, si su significado no es obvio por el contexto.

2. Deconstrucción de tuplas

¿Qué es la deconstrucción?

La deconstrucción es el proceso de "desempaquetar" una tupla en variables separadas, para trabajar con ellas de forma cómoda. O sea, puedes sacar de la tupla (Edad: 5, Nombre: "Fluffy") dos variables: edad y nombre.

Analogía: Imagina que la tupla es una caja con compartimentos etiquetados. Deconstruir es como sacar todo de la caja y ponerlo en su sitio en la mesa.

Sintaxis de deconstrucción


var pet = (Edad: 5, Nombre: "Fluffy");
var (edad, nombre) = pet;
Console.WriteLine($"{nombre} — {edad} años");
Deconstrucción de tupla en variables

Ahora tenemos dos variables: edad y nombre. Reciben los valores de la tupla. Los nombres a la izquierda (edad, nombre) no tienen que coincidir con los de la tupla, son simplemente nuevas variables locales.

Deconstrucción del valor de retorno de una función

Muchas veces las tuplas se usan para devolver varios valores de una función. Ahí la deconstrucción es especialmente cómoda:


public static (double minimo, double maximo) GetMinMax(int[] datos)
{
    int minimo = datos.Min();
    int maximo = datos.Max();
    return (minimo, maximo);
}

var numeros = new[] { 1, 2, 3, 4, 5 };
var (valorMinimo, valorMaximo) = GetMinMax(numeros);
Console.WriteLine($"Mínimo: {valorMinimo}, máximo: {valorMaximo}");
Deconstrucción del valor de retorno de una función

Fíjate que en la deconstrucción puedes llamar a las variables como te venga mejor en ese contexto.

Deconstrucción con var

var (a, b) = (10, 20); // int a = 10, b = 20

Deconstrucción y discard _

A veces no necesitas todos los elementos de la tupla. Puedes ignorarlos usando _ (discard). El discard (_) en la tupla es solo una forma de decir "sé que aquí hay otro elemento, pero no lo quiero, no crees una variable para él".

Así, deconstruyes la tupla pero dejas un "hueco" donde no necesitas el valor. ¡Corto, cómodo y sin complicaciones!


var pet = (Edad: 5, Nombre: "Fluffy", EsFeliz: true);
var (edad, _, esFeliz) = pet; // solo edad y esFeliz, nombre ignorado
Deconstrucción con discard _

Dato curioso: el discard se usa mucho para no llenar el espacio de nombres con variables que no necesitas.

Deconstrucción en el bucle foreach

En C# puedes recorrer un array de tuplas deconstruyendo directamente en el propio foreach:


var mascotas = new (string Nombre, int Edad)[]
{
    ("Fluffy", 5),
    ("Luna", 3),
    ("Johnny", 7)
};

foreach (var (nombre, edad) in mascotas)
{
    Console.WriteLine($"{nombre} — {edad} años");
}
Deconstrucción de tuplas en foreach

3. Cómo funcionan los nombres de los elementos y el tipado

Comportamiento de los elementos nombrados

Los nombres de los elementos de la tupla son "azúcar sintáctico", o sea, solo para humanos. Al compilar, los nombres se convierten en campos internos Item1, Item2, etc., pero el IDE y el compilador guardan los nombres para que los puedas usar.

Influencia en la compatibilidad de tipos y casting

Dos tuplas con el mismo número de elementos y tipos, pero con nombres diferentes, se consideran del mismo tipo para el compilador. Los nombres de los elementos no forman parte de la definición del tipo:


var t1 = (X: 42, Y: 13);
var t2 = (A: 42, B: 13);
t1 = t2; // OK
Console.WriteLine(t1.X); // 42
Compatibilidad de tuplas con diferentes nombres de elementos

Pero al trabajar con expresiones y sugerencias de IntelliSense, se usarán los nombres de la parte izquierda (donde asignas), no los de la derecha.

Nombrado implícito y explícito

Ya lo vimos, pero por si acaso: puedes crear tuplas con algunos elementos nombrados, o sin nombrar ninguno — entonces serán simplemente Item1 y así.


var punto = (X: 10, 20); // X y Item2
Console.WriteLine(punto.X);     // 10
Console.WriteLine(punto.Item2); // 20
Tupla parcialmente nombrada

Consejo: nombra siempre los elementos si la tupla tiene más de uno o dos elementos, o si el significado del valor no es claro por el contexto.

4. Errores típicos y particularidades al trabajar con nombres y deconstrucción

Error nº1: “traslado” de nombres al asignar diferentes tuplas
Si primero declaras una tupla con unos nombres, y luego le asignas otra tupla sin nombres (o con otros nombres), en IntelliSense seguirán apareciendo los nombres originales. Por ejemplo:


var original = (X: 1, Y: 2);
var alias = original;            // alias.X == 1, alias.Y == 2

original = (10, 20);             // tupla sin nombres
Console.WriteLine(alias.X);      // sigue funcionando, pero alias sigue guardando los nombres antiguos

Error nº2: duplicar nombres de elementos.
No puedes poner el mismo nombre a dos elementos — el compilador dará el mensaje “Duplicate tuple element name”:


var tuplaMala = (A: 1, A: 2);     // Error CS8122: Duplicate tuple element name 'A'

Error nº3: deconstrucción incorrecta por número de elementos.
Al deconstruir, el número de variables debe coincidir exactamente con el tamaño de la tupla. Si no, da error:


var pet = (Edad: 5, Nombre: "Fluffy");
var (edad, nombre, humor) = pet;     // Error CS8124: Tuple must contain exactly 3 elements

Error nº4: mal uso de discard _
Ignorar elementos con _ funciona para cada sitio por separado y no “une” los huecos en uno solo. Por ejemplo, si intentas saltarte dos elementos con un solo _, te dará error:


var datos = (1, 2, 3);
var (_, x, _) = datos;            // Correcto: saltados primer y tercer elemento
var (_, _) = datos;               // Error CS8124: Tuple must contain exactly 2 elements

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION