Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Tip
Questo articolo fa parte della sezione Nozioni fondamentali per gli sviluppatori che già conoscono almeno un linguaggio di programmazione e stanno imparando C#. Se non si ha familiarità con la programmazione, iniziare prima con le esercitazioni introduttive . Gli sviluppatori C# esperti possono usare i riferimenti ai modelli per la sintassi e le regole complete.
Venire da un'altra lingua? I pattern di C# svolgono un ruolo simile al pattern matching di Java e ai casi match di Python. C# usa modelli in is espressioni, switch istruzioni ed switch espressioni.
La corrispondenza di modelli applica un modello a un'espressione. Un pattern è una condizione con cui verificare l'espressione di input. L'input del modello è quell'espressione. C# valuta l'espressione di input; il risultato è il valore valutato. Il criterio verifica se tale valore ha un tipo specifico, è uguale a un determinato valore o ha una forma specifica. Quando un criterio corrisponde, il codice può usare le informazioni apprese dal test, ad esempio un tipo più specifico o un valore estratto da un oggetto .
È possibile usare un modello in tre contesti:
- Sul lato destro dell'operatore
is. - In una etichetta
casedi un'istruzioneswitch. - In un ramo di un'espressione
switch.
I modelli sono spesso più chiari di una sequenza di istruzioni di confronto perché ogni ramo descrive i dati gestiti. Ad esempio, il metodo seguente usa un'espressione switch per scegliere un messaggio di recapito:
static string GetDeliveryMessage(Delivery? delivery) =>
delivery switch
{
null => "No delivery was scheduled.",
ExpressDelivery express => $"Express package {express.TrackingCode}",
StandardDelivery { Days: <= 2 } => "Standard delivery arriving soon",
_ => "Standard delivery"
};
I modelli ricorsivi hanno espressioni di input personalizzate. In StandardDelivery { Days: <= 2 }, il criterio esterno riceve l'espressione delivery. Il modello ricorsivo <= 2 riceve l'espressione della proprietà Days dall'oggetto StandardDelivery corrispondente.
L'espressione prima di switch è l'espressione di input. Ogni riga all'interno delle parentesi graffe è un ramo dell'interruttore. Il modello appare prima di => e il risultato appare dopo. C# valuta l'espressione di input, quindi seleziona il primo ramo, nell'ordine in cui appare nel testo, il cui modello trova corrispondenza e la cui guardia facoltativa è true. La protezione facoltativa è una condizione booleana when aggiuntiva scritta dopo il modello. L'esempio precedente ha mostrato i modelli seguenti:
-
nullè un modello costante. Verifica se l'espressionedeliveryrestituiscenull. -
ExpressDelivery expressè un modello di dichiarazione con due parti.ExpressDeliveryè la parte della prova di tipo. Verifica se il valore valutato è un oggetto non Null il cui tipo di runtime è compatibile conExpressDelivery.expressè la dichiarazione di variabile: dichiara una variabile denominataexpresse le assegna l'oggettoExpressDeliverycorrispondente. -
StandardDelivery { Days: <= 2 }inizia con un test di tipo.StandardDeliveryverifica se il valore valutato è un oggetto non Null di tale tipo. Le parentesi graffe contengono un modello di proprietà.Daysassegna un nome alla proprietà da esaminare, in modo che l'espressioneDaysdi proprietà diventi l'input del modello ricorsivo. La<= 2parte è un modello relazionale, che verifica se il valore valutato è minore o uguale a2. -
_(carattere di sottolineatura) è il modello di eliminazione. Corrisponde a ogni valore valutato, inclusonull. Poiché i rami precedenti gestiscono giànull, le consegne espresse e le consegne standard che arrivano entro due giorni, quest'ultimo ramo gestisce tutti i valori rimanenti.
Un braccio senza guardia when non è sorvegliato. Tutte le braccia del primo esempio sono senza guardia. Se un braccio non sorvegliato precedente corrisponde a ogni valore valutato che un braccio successivo potrebbe corrispondere, il braccio successivo viene sottosumato. Un modello subsumed è uno in cui ogni possibile valore di input corrispondente corrisponde già a un braccio switch precedente. Non può mai corrispondere, quindi il compilatore segnala un errore. Il braccio di eliminazione (_) deve venire per ultimo perché corrisponde a ogni espressione di input. Un ramo con guardia non sussume un ramo successivo basandosi unicamente sul suo pattern, perché la guardia potrebbe essere false.
Un'espressione switch è esaustiva quando le sue clausole coprono tutte le possibili espressioni di input. Il primo esempio è esaustivo perché il braccio di scarta finale gestisce qualsiasi cosa le braccia precedenti non corrispondono. Il compilatore avvisa quando rileva un possibile valore di input che nessun ramo gestisce. Il compilatore non può dimostrare esaustività per ogni combinazione di modelli, ma questa diagnostica consente di scrivere codice corretto di corrispondenza dei criteri. Per informazioni dettagliate sulla corrispondenza, la sussunzione e le regole di esaustività, consultare il riferimento ai pattern.
Testare una condizione con is
Usare l'operatore is quando è necessario un test booleano. Il codice seguente valuta l'espressione delivery e applica il modello ExpressDelivery expressdi dichiarazione . La parte relativa al tipo corrisponde quando il valore valutato è non nullo e il suo tipo in fase di esecuzione è compatibile con ExpressDelivery. Quando il criterio corrisponde, la designazione della variabile dichiara express:
static void PrintTrackingCode(Delivery delivery)
{
if (delivery is ExpressDelivery express)
{
Console.WriteLine($"Track express package {express.TrackingCode}");
}
}
Il compilatore tiene traccia del fatto che una variabile locale sia stata assegnata prima della lettura del codice. Questo rilevamento è denominato assegnazione definita. All'interno del if blocco, la condizione può essere true solo quando il criterio ha assegnato l'oggetto corrispondente a express. Il compilatore sa quindi che express è sicuramente assegnato in tale posizione. Il codice può usare in modo sicuro la relativa TrackingCode proprietà. Non è necessario un cast separato. Se è necessario solo il test di tipo e non è necessario dichiarare una variabile, usare un modello di tipo, ad esempio delivery is ExpressDelivery.
Usare is null o is not null per le verifiche di null. Questi modelli non chiamano un operatore != o == definito dall'utente.
static void PrintPackageStatus(Delivery? delivery)
{
if (delivery is null)
{
Console.WriteLine("No package is available.");
}
else
{
Console.WriteLine("A package is ready to track.");
}
}
Per ulteriori informazioni sulla sicurezza rispetto ai valori null, vedere tipi riferimento annullabili.
Scegliere tra un'istruzione e un'espressione
I modelli funzionano con entrambe le forme di switch:
- Usare un'
switchistruzione quando ogni corrispondenza deve eseguire una o più istruzioni. - Usare un'espressione
switchquando ogni corrispondenza deve produrre un valore.
La seguente istruzione switch segnala un aggiornamento sulla consegna. Il ramo di consegna rapida scrive due messaggi, quindi un'istruzione si inserisce naturalmente:
static void PrintDeliveryUpdate(Delivery? delivery)
{
switch (delivery)
{
case null:
Console.WriteLine("No delivery was scheduled.");
break;
case ExpressDelivery express:
Console.WriteLine($"Express delivery {express.TrackingCode} is ready.");
Console.WriteLine("Notify the priority desk.");
break;
case StandardDelivery standard:
Console.WriteLine($"Standard delivery arrives in {standard.Days} days.");
break;
default:
Console.WriteLine("Another delivery type is scheduled.");
break;
}
}
Ognuno case applica un criterio all'espressione delivery . La sezione corrispondente può eseguire un numero qualsiasi di istruzioni prima break di uscire dall'opzione. La default sezione gestisce qualsiasi elemento che i case precedenti non corrispondono.
L'espressione switch seguente sostituisce una if / else if catena che assegna un risultato:
static string GetStatusMessage(StandardDelivery delivery) =>
delivery.Days switch
{
0 => "Delivered today",
1 => "Arriving tomorrow",
<= 3 => "Arriving soon",
_ => "In transit"
};
Un'espressione switch è concisa perché ogni arm ha lo stesso scopo: produrre il valore restituito. Usare un'istruzione switch quando i rami eseguono azioni e usare un'espressione switch quando i rami calcolano un risultato.
Categorie di modelli
C# include modelli per i tipi comuni di test dei dati:
| Categoria di modelli | Che cosa testa |
|---|---|
Dichiarazione, costante e var modelli |
Tipo di runtime, valore costante specifico o qualsiasi valore che si desidera acquisire |
| Modelli di tipo | Tipo di runtime senza dichiarare una variabile |
| Modelli di proprietà e posizionali | Proprietà, campi o valori deconstruiti |
| Modelli relazionali e logici | Confronti e combinazioni come and, or e not |
| Modelli di elenco | Valori e forma di un elenco o di una matrice |
| Eliminare modelli e eliminazioni | Qualsiasi valore rimanente o un valore ignorato intenzionalmente dal codice |
Gli articoli fondamentali collegati nella tabella forniscono una copertura mirata delle categorie attualmente documentate in questa sezione. Per una sintassi completa ed esempi per tutte le categorie di criteri, vedere le informazioni di riferimento sui modelli.