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#. Iniziate con la panoramica della corrispondenza dei modelli se non conoscete ancora i modelli. Per informazioni complete sulle regole del linguaggio, vedere Modelli di proprietà e modelli posizionabili nella guida di riferimento al linguaggio.
I pattern di proprietà e i pattern posizionali verificano entrambi parti di un valore. La differenza è il modo in cui identificano tali parti:
- Un criterio di proprietà assegna un nome alle proprietà o ai campi da testare.
- Un modello posizionale identifica i valori in base all'ordine.
Una decostruzione espone un set ordinato di valori dei componenti. Una tupla ha già un ordine degli elementi; vedi decostruire le tuple. Per un altro tipo, un Deconstruct metodo definisce i valori dei componenti esposti e il relativo ordine.
Confrontare nomi e posizioni
Il modello di proprietà seguente verifica due proprietà denominate di una lettura meteo, con valori di temperatura in gradi Celsius:
static bool IsHotAndHumid(WeatherReading reading) =>
reading is { TemperatureC: > 30, HumidityPercent: > 70 };
sealed record WeatherReading(int TemperatureC, int HumidityPercent);
Il modello posizionale seguente verifica un valore di segnale seguito da un valore booleano:
static string GetCrossingInstruction(
PedestrianSignal signal, bool crossingIsClear) =>
(signal, crossingIsClear) switch
{
(PedestrianSignal.Walk, true) => "Cross now",
(PedestrianSignal.Walk, false) => "Wait for the crossing to clear",
_ => "Wait for the walk signal"
};
enum PedestrianSignal
{
Stop,
Walk
}
Il modello di proprietà identifica gli input in base ai nomi TemperatureC e HumidityPercenta . Il codice di incrocio crea una tupla a partire dai valori separati signal e crossingIsClear. Il modello di tupla identifica quindi tali valori in base all'ordine: signal primo e crossingIsClear secondo. Un modello posizionale è particolarmente adatto perché questa tupla appena creata ha solo due valori e il loro ordine ha un significato chiaro nella decisione sull’attraversamento.
Scegliere un modello di proprietà quando i nomi dei membri aiutano a spiegare il test. I modelli di proprietà sono in genere più chiari per classi, struct e record. Scegliere un modello posizionale quando l'ordine dà già un significato ovvio ai valori. I modelli posizionali sono più utili con le tuple, che combinano più valori correlati in un unico valore con un ordine fisso.
Seguire gli input annidati all'interno di modelli ricorsivi
I modelli di proprietà e posizione sono modelli ricorsivi: applicano un altro modello a ogni proprietà, campo o posizione selezionati. Il valore selezionato diventa l'input di quel modello annidato.
In IsHotAndHumid, l'espressione reading è l'input del criterio di proprietà. C# valuta prima l'espressione e poi esegue il confronto. Il modello ottiene due valori dall'oggetto risultante:
- Il modello
> 30relazionale verifica il valore diTemperatureC. - Il modello
> 70relazionale verifica il valore diHumidityPercent.
Un test di tipo esterno è facoltativo e le clausole pattern ricorsive possono essere vuote. Ad esempio, il modello { } di proprietà vuoto corrisponde a qualsiasi valore valutato non Null.
I criteri di proprietà e quelli posizionali corrispondono solo a valori non nulli già valutati. Quando null fa parte del dominio di input, scegliere prima un modello ricorsivo che verifica la presenza di un valore non Null:
static string DescribeNullableInput(object? value)
{
if (value is not { } nonNullValue)
{
return "No value";
}
return nonNullValue switch
{
DateTime => "Date",
string => "Text",
_ => "Another type"
};
}
L'espressione di input è value. C# lo valuta e il { } modello di proprietà testa il valore risultante per non Null prima di assegnarlo a nonNullValue. L'espressione switch seguente può quindi testare più tipi di runtime possibili. I modelli DateTime di tipo e string non hanno alcuna designazione perché il metodo deve identificare solo ogni tipo, non acquisire il relativo valore.
Quando le clausole pattern ricorsive contengono modelli annidati, ogni proprietà, campo o posizione selezionata diventa l'input per il modello annidato.
È possibile aggiungere un test di tipo prima delle parentesi graffe quando l'espressione di input può restituire tipi diversi. È anche possibile usare un percorso membro per testare una proprietà annidata:
static string DescribeDate(object? value) =>
value switch
{
DateTime { Date.DayOfWeek:
DayOfWeek.Saturday or DayOfWeek.Sunday } => "Weekend date",
DateTime => "Weekday date",
null => "No date",
_ => "Not a date"
};
value è l'espressione di ingresso. C# lo valuta prima e verifica se il valore risultante è un DateTime. Il valore della Date proprietà diventa quindi l'input per l'accesso al DayOfWeek membro. Infine, il DayOfWeek valore diventa l'input del modello logico che testa due costanti. La corrispondenza ha esito positivo quando il valore esterno ha il tipo specificato e ogni oggetto necessario lungo il percorso del membro non è Null.
Confronta i pattern con le istruzioni di diramazione
Il metodo precedente DescribeDate esprime quattro risultati come modelli:
static string DescribeDate(object? value) =>
value switch
{
DateTime { Date.DayOfWeek:
DayOfWeek.Saturday or DayOfWeek.Sunday } => "Weekend date",
DateTime => "Weekday date",
null => "No date",
_ => "Not a date"
};
Il metodo seguente produce gli stessi risultati con una serie di istruzioni di diramazione imperativa:
static string DescribeDateWithBranches(object? value)
{
if (value is DateTime date)
{
if (date.DayOfWeek == DayOfWeek.Saturday ||
date.DayOfWeek == DayOfWeek.Sunday)
{
return "Weekend date";
}
return "Weekday date";
}
if (value is null)
{
return "No date";
}
return "Not a date";
}
La versione basata su pattern mantiene insieme i risultati possibili quando diversi rami testano il tipo e la forma di un valore. La versione imperativa esplicita ogni passaggio di test e di ritorno. In una condizione, ciascuna delle due forme potrebbe apparire simile. Man mano che aumenta il numero di rami correlati, i modelli possono semplificare il confronto tra le alternative.