CodeGym /Corsi /C# SELF /Nominare gli elementi e deconstruct dei tuple

Nominare gli elementi e deconstruct dei tuple

C# SELF
Livello 11 , Lezione 2
Disponibile

1. Nominare i tuple: contesto per la deconstruct

Nella lezione precedente abbiamo già visto gli elementi nominati nei tuple, che rendono il codice molto più leggibile, perché puoi accedere ai valori non tramite i generici Item1, Item2, ma con nomi che hanno senso (tipo person.Name). Dare nomi agli elementi del tuple è super importante, soprattutto quando li usi come valori di ritorno da metodi, parametri o proprietà. Proprio il naming è la base per una deconstruct comoda, che vediamo tra poco in questa lezione.

Ricorda, puoi dare i nomi sia quando inizializzi il tuple tramite literal, sia nella signature del valore di ritorno di un metodo, proprietà o campo.

Esempio con metodo: Elementi nominati nel valore di ritorno del metodo


public static (int Età, string Nome) GetPetInfo()
{
    return (Età: 5, Nome: "Barsik");
}

// Uso:
var info = GetPetInfo();
Console.WriteLine($"{info.Nome} — {info.Età} anni");

Esempio con campo/proprietà: Elementi nominati nel campo/proprietà


public (int Larghezza, int Altezza) ImageSize = (1024, 768);

Ricorda: se non dai nomi espliciti, gli elementi saranno comunque accessibili tramite Item1, Item2 ecc. Questo può rendere il codice meno leggibile, soprattutto quando usi il tuple più avanti. Ecco perché è sempre meglio dare nomi chiari agli elementi, se il loro significato non è ovvio dal contesto.

2. Deconstruct dei tuple

Cos'è la deconstruct?

La deconstruct è il processo di "spacchettare" un tuple in variabili separate, così puoi lavorarci comodamente. Cioè, da un tuple tipo (Età: 5, Nome: "Barsik") puoi ottenere due variabili: età e nome.

Analogia: Immagina che il tuple sia una scatola con scomparti etichettati. La deconstruct è quando svuoti subito il contenuto della scatola e lo metti nei posti giusti sulla scrivania.

Sintassi della deconstruct


var pet = (Età: 5, Nome: "Barsik");
var (età, nome) = pet;
Console.WriteLine($"{nome} — {età} anni");
Deconstruct di un tuple in variabili

Ora abbiamo due variabili: età e nome. Hanno preso i valori dal tuple. I nomi a sinistra (età, nome) non devono per forza essere uguali a quelli nel tuple, sono solo nuove variabili locali.

Deconstruct del valore di ritorno di una funzione

Spesso i tuple si usano per restituire più valori da una funzione. Lì la deconstruct è davvero comoda:


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

var numeri = new[] { 1, 2, 3, 4, 5 };
var (valoreMinimo, valoreMassimo) = GetMinMax(numeri);
Console.WriteLine($"Minimo: {valoreMinimo}, massimo: {valoreMassimo}");
Deconstruct del valore di ritorno di una funzione

Nota che nella deconstruct puoi chiamare le variabili come vuoi, in base a quello che ti serve nel contesto.

Deconstruct con var

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

Deconstruct e discard _

A volte non ti servono tutti gli elementi del tuple. Puoi ignorarli usando _ (discard). Il discard (_) in un tuple è solo un modo per dire "so che qui c'è un altro elemento, ma non mi interessa, non creare una variabile per lui".

Così, deconstruct il tuple ma lasci un "buco" dove non ti serve il valore. Semplice, comodo e senza compromessi!


var pet = (Età: 5, Nome: "Barsik", ÈFelice: true);
var (età, _, èFelice) = pet; // solo età e èFelice, nome ignorato
Deconstruct con discard _

Curiosità: il discard si usa spesso per non riempire lo scope di variabili inutili.

Deconstruct in un ciclo foreach

In C# puoi scorrere un array di tuple con la deconstruct direttamente nella dichiarazione del foreach:


var pets = new (string Nome, int Età)[]
{
    ("Barsik", 5),
    ("Musja", 3),
    ("Dzhonni", 7)
};

foreach (var (nome, età) in pets)
{
    Console.WriteLine($"{nome} — {età} anni");
}
Deconstruct dei tuple in foreach

3. Come funzionano i nomi degli elementi e la tipizzazione

Comportamento degli elementi nominati

I nomi degli elementi del tuple sono "syntactic sugar", cioè una comodità per chi legge. Durante la compilazione i nomi diventano i campi interni Item1, Item2 ecc., ma IDE e compilatore tengono i nomi per farteli usare.

Effetto sulla compatibilità dei tipi e cast

Due tuple con lo stesso numero di elementi e tipi, ma nomi diversi, sono considerate dello stesso tipo dal compilatore. I nomi degli elementi non fanno parte della definizione del tipo:


var t1 = (X: 42, Y: 13);
var t2 = (A: 42, B: 13);
t1 = t2; // OK
Console.WriteLine(t1.X); // 42
Compatibilità di tuple con nomi diversi degli elementi

Però, quando lavori con espressioni e suggerimenti IntelliSense, verranno usati i nomi della parte sinistra (dove assegni), non quelli della destra.

Nomi impliciti ed espliciti

L'abbiamo già visto, ma per sicurezza: puoi creare tuple con elementi parzialmente nominati, oppure senza nomi — in quel caso saranno solo Item1 ecc.


var punto = (X: 10, 20); // X e Item2
Console.WriteLine(punto.X);     // 10
Console.WriteLine(punto.Item2); // 20
Tuple parzialmente nominato

Consiglio: dai sempre un nome agli elementi se il tuple ha più di uno o due elementi, o se il significato non è chiaro dal contesto.

4. Errori tipici e particolarità con nomi e deconstruct

Errore n°1: "trasloco" dei nomi quando assegni tuple diversi
Se prima hai dichiarato un tuple con certi nomi, poi gli assegni un altro tuple senza nomi (o con nomi diversi), in IntelliSense vedrai comunque i nomi originali. Esempio:


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

originale = (10, 20);             // tuple senza nomi
Console.WriteLine(alias.X);      // funziona ancora, ma alias ha ancora i vecchi nomi

Errore n°2: duplicazione dei nomi degli elementi.
Non puoi dare lo stesso nome a due elementi — il compilatore ti dirà "Duplicate tuple element name":


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

Errore n°3: deconstruct sbagliata per numero di elementi.
Quando fai la deconstruct, il numero di variabili deve essere esattamente uguale alla dimensione del tuple. Qualsiasi differenza dà errore:


var pet = (Età: 5, Nome: "Barsik");
var (età, nome, umore) = pet;     // Errore CS8124: Tuple must contain exactly 3 elements

Errore n°4: uso sbagliato del discard _
Ignorare elementi con _ funziona per ogni posizione separatamente e non "unisce" i buchi in uno solo. Se provi a saltare due elementi con un solo _, ottieni errore:


var dati = (1, 2, 3);
var (_, x, _) = dati;            // Ok: saltati primo e terzo elemento
var (_, _) = dati;               // Errore CS8124: Tuple must contain exactly 2 elements

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