Modelli relazionali, logici e racchiusi tra parentesi

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 le regole complete del linguaggio, vedere Modelli relazionali e modelli logici nella guida di riferimento al linguaggio.

I modelli relazionali e logici descrivono intervalli, alternative ed esclusioni. Il metodo seguente li combina per classificare una temperatura:

static string ClassifyTemperature(int temperature) =>
    temperature switch
    {
        < 0 => "Below freezing",
        >= 18 and <= 24 => "Comfortable",
        (>= 0 and < 10) or > 30 => "Far outside the comfortable range",
        _ => "Cool or warm"
    };

L'espressione temperature è l'input del modello. C# lo valuta una sola volta e ogni arm switch testa il valore risultante. Le braccia dimostrano questi test:

  • < 0 verifica un limite.
  • >= 18 and <= 24 verifica un intervallo.
  • (>= 0 and < 10) or > 30 verifica due intervalli alternativi.

Questo articolo illustra sia i modelli che le condizioni imperative, in modo da poter apprendere ogni modulo e confrontare il modo in cui esprimono le stesse decisioni. Una singola condizione può apparire simile in entrambe le forme. I modelli possono semplificare la lettura di una serie di rami correlati mantenendo le scelte accanto ai risultati. Scegliere il modulo che semplifica la comprensione del codice.

Confrontare i valori con i modelli relazionali

Un modello relazionale confronta l'input del modello con una costante in fase di compilazione usando <, ><=, o >=. Una costante in fase di compilazione è un valore che il compilatore può valutare durante la compilazione del programma. I valori letterali numerici e di caratteri e const le variabili di tipi numerici o di caratteri compatibili sono esempi rappresentativi. Le variabili, le proprietà, le chiamate ai metodi e static readonly i campi ordinari non sono costanti in fase di compilazione. Nell'esempio di apertura, sia >= 18 che <= 24 testano lo stesso valore valutato temperature .

Lo stesso simbolo relazionale può comparire in un'espressione ordinaria o in un modello. Nell'esempio seguente vengono usate entrambe le forme con una temperatura:

static void ShowExpressionAndPattern(int temperature, int threshold)
{
    bool belowThreshold = temperature < threshold;
    bool belowFreezing = temperature is < 0;

    string description = temperature switch
    {
        < 0 => "Freezing",
        0 => "Freezing point",
        > 0 => "Above freezing"
    };

    Console.WriteLine(
        $"Below threshold: {belowThreshold}; " +
        $"below freezing: {belowFreezing}; {description}");
}

temperature < threshold è un'espressione relazionale. Valuta entrambi gli operandi e produce un oggetto bool. Ciascuno dei due operandi può essere un'espressione non costante.

In temperature, temperature is < 0 è l'espressione di input del modello. C# lo valuta e il modello < 0 relazionale testa il valore risultante. Nel ramo dello switch < 0 => "Freezing", l'espressione prima di switch fornisce l'input, quindi il modello contiene solo < 0.

L'espressione può essere confrontata temperature con la variabile threshold. Un operando modello relazionale deve essere una costante in fase di compilazione, quindi usare l'espressione relazionale quando il valore di confronto è una variabile. Quando il valore di confronto è costante, entrambi i moduli possono funzionare.

Quando l'operando destro è costante, scegliere principalmente per la leggibilità. Un'espressione relazionale spesso si adatta a un confronto diretto. Un modello relazionale si compone con altri modelli e si adatta naturalmente quando vengono mappati diversi intervalli per cambiare i risultati.

Combinare condizioni con modelli logici

I modelli logici combinano o negano i criteri con gli operatori anddi criteri , ore not:

  • Un modello and trova corrispondenza quando entrambi i modelli annidati trovano corrispondenza.
  • Un or modello corrisponde se si verifica una corrispondenza con uno dei due modelli annidati.
  • Un not modello riesce quando il suo modello annidato fallisce.

Nell'esempio di apertura viene and utilizzato per descrivere un intervallo e or descrivere le alternative. Un not pattern può escludere un valore, come in status is not Status.Complete. I metodi seguenti mostrano entrambi i moduli in modo da poter apprendere la sintassi e confrontare il modo in cui esprimono lo stesso test:

static bool IsWeekendPattern(DayOfWeek day) =>
    day is DayOfWeek.Saturday or DayOfWeek.Sunday;

static bool IsWeekendImperative(DayOfWeek day) =>
    day == DayOfWeek.Saturday || day == DayOfWeek.Sunday;

Il modulo pattern usa due modelli costanti uniti da or. Il modulo imperativo usa due espressioni di uguaglianza unite dall'operatore ||OR condizionale . Entrambe le forme sono concise e chiare per questa singola condizione. Scegliere il modulo più adatto al codice circostante. I modelli spesso chiariscono diverse scelte correlate in un switch, come nell'esempio iniziale.

Gli operatori pattern formano modelli anziché espressioni booleane: and corrisponde alla congiunzione dei criteri, or alle alternative di criteri e not alla negazione dei criteri. Le espressioni booleane usano &&, ||e !. Scegli or quando più alternative di modello producono lo stesso risultato. Scegliere not quando si esprime il modello escluso è più chiaro rispetto all'elenco di ogni valore accettato.

Raggruppare i modelli con parentesi

Un modello tra parentesi usa le parentesi per mostrare o modificare la modalità di raggruppamento dei modelli annidati. Il vincolo determina quali operandi del pattern un operatore raggruppa insieme, in modo simile al raggruppamento implicito quando non vengono scritte parentesi. C# specifica l'ordine di associazione seguente:

  1. not
  2. and
  3. or

Il test seguente accetta le priorità da 1 a 3 o la priorità speciale 9:

static bool IsAcceptedPriority(int priority) =>
    priority is (>= 1 and <= 3) or 9;

Il compilatore raggruppa and prima ordi . Le parentesi rendono esplicito il raggruppamento previsto e le due alternative facili da vedere: l'intervallo compreso tra 1 e 3 o 9. Per garantire la leggibilità, utilizzare le parentesi ogni volta che uno schema combina and e or, oppure quando not si applica a uno schema composto. Le parentesi possono anche modificare il raggruppamento predefinito, come in not (>= 1 and <= 3).

L'ordine della verifica eseguita in fase di esecuzione per i pattern annidati non è specificato e gli operatori di pattern seguono le regole di corrispondenza dei pattern anziché le regole booleane di short-circuit. Scrivere modelli annidati in modo che il risultato sia indipendente dall'ordine di controllo.

Usare una guardia when per una condizione distinta

I modelli logici funzionano meglio quando i modelli annidati descrivono il valore di input stesso. Una when protezione è una condizione booleana aggiuntiva su un'etichetta o un case braccio switch. Usare una protezione quando la decisione dipende anche da informazioni separate dall'input del modello.

L'avviso seguente dipende dalla temperatura e da un valore separato isOutdoors :

static string GetHeatWarning(int temperature, bool isOutdoors) =>
    temperature switch
    {
        > 35 when isOutdoors => "High heat outdoors",
        > 35 => "High heat",
        _ => "No heat warning"
    };

Il modello > 35 relazionale descrive l'input temperature . La protezione when isOutdoors controlla un valore separato. Anche una clausola di guardia è preferibile quando la condizione richiede una chiamata di metodo o un'espressione booleana che la sintassi del pattern non esprime chiaramente.

Usate modelli relazionali e logici quando rendono più facile individuare le forme o i valori consentiti per l'input, soprattutto quando si confrontano più rami di uno switch. Usare un'espressione booleana comune quando indica più semplicemente una condizione diretta. Usare una when protezione quando una scelta switch dipende da un valore separato o da una condizione espressa meglio come espressione booleana.

Vedere anche