11 Criteri e criteri di ricerca
11.1 Generale
Un modello è una forma sintattica che può essere utilizzata con l'operatore is
(§12.12.12) e in un switch_statement (§13.8.3) per esprimere la forma dei dati rispetto ai quali confrontare i dati in ingresso. Un criterio viene testato sull'espressione di un'istruzione switch o su un relational_expression sul lato sinistro di un is
operatore, ognuno dei quali viene definito valore di input del criterio.
11.2 Moduli pattern
11.2.1 Generale
Un modello può avere una delle forme seguenti:
pattern
: declaration_pattern
| constant_pattern
| var_pattern
;
Un declaration_pattern e un var_pattern possono comportare la dichiarazione di una variabile locale.
Ogni modulo modello definisce il set di tipi per i valori di input a cui può essere applicato il modello. Un criterio P
è applicabile a un tipo T
se T
è tra i tipi i cui valori possono corrispondere al criterio. Si tratta di un errore in fase di compilazione se un criterio P
viene visualizzato in un programma in modo che corrisponda a un valore di input del modello (§11.1) di tipo T
se P
non è applicabile a T
.
Esempio: l'esempio seguente genera un errore in fase di compilazione perché il tipo in fase di compilazione di
v
èTextReader
. Una variabile di tipoTextReader
non può mai avere un valore compatibile con il riferimento constring
:TextReader v = Console.In; // compile-time type of 'v' is 'TextReader' if (v is string) // compile-time error { // code assuming v is a string }
Tuttavia, il codice seguente non genera un errore in fase di compilazione perché il tipo in fase di compilazione di
v
èobject
. Una variabile di tipoobject
può avere un valore compatibile con il riferimento constring
:object v = Console.In; if (v is string s) { // code assuming v is a string }
esempio finale
Ogni modulo pattern definisce il set di valori per cui il criterio corrisponde al valore in fase di esecuzione.
Modello di dichiarazione 11.2.2
Un declaration_pattern viene usato per verificare che un valore abbia un tipo specificato e, se il test ha esito positivo, specificare il valore in una variabile di tale tipo.
declaration_pattern
: type simple_designation
;
simple_designation
: single_variable_designation
;
single_variable_designation
: identifier
;
Il tipo di runtime del valore viene testato sul tipo nel criterio usando le stesse regole specificate nell'operatore is-type (§12.12.12.12.1). Se il test ha esito positivo, il criterio corrisponde a tale valore. Si tratta di un errore in fase di compilazione se il tipo è un tipo valore nullable (§8.3.12). Questo modulo di pattern non corrisponde mai a un null
valore.
Nota: l'espressione
e is T
is-type e il criterioe is T _
di dichiarazione sono equivalenti quandoT
non è un tipo nullable. nota finale
Dato un valore di input del criterio (§11.1) e, se il simple_designation è l'identificatore _
, indica un'eliminazione (§9.2.9.1) e il valore di e non è associato ad alcun elemento. Anche se una variabile dichiarata con il nome _
può trovarsi nell'ambito in quel punto, tale variabile denominata non viene visualizzata in questo contesto. Se simple_designation è qualsiasi altro identificatore, viene introdotta una variabile locale (§9.2.9) del tipo specificato denominato dall'identificatore specificato. A tale variabile locale viene assegnato il valore del valore di input del pattern quando il criterio corrisponde al valore.
Alcune combinazioni di tipo statico del valore di input del modello e il tipo specificato sono considerate incompatibili e generano un errore in fase di compilazione. Si dice che un valore di tipo E
statico sia compatibile con il tipo T
se esiste una conversione di identità, una conversione di riferimento implicita o esplicita, una conversione boxing o una conversione unboxing da E
a T
o se E
T
è un tipo aperto (§8.4.3). Un modello di dichiarazione che denomina un tipo T
è applicabile a ogni tipo E
per il quale E
è compatibile con il modello con T
.
Nota: il supporto per i tipi aperti può essere più utile quando si controllano i tipi che possono essere struct o tipi di classe ed è consigliabile evitare la conversione boxing. nota finale
Esempio: il modello di dichiarazione è utile per l'esecuzione di test di tipi di riferimento in fase di esecuzione e sostituisce il linguaggio
var v = expr as Type; if (v != null) { /* code using v */ }
con il leggermente più conciso
if (expr is Type v) { /* code using v */ }
esempio finale
Si tratta di un errore se il tipo è un tipo di valore nullable.
Esempio: il modello di dichiarazione può essere usato per testare i valori dei tipi nullable: un valore di tipo (o boxed
T
) corrisponde a un criterioT2 id
di tipo se il valore è diverso da null edT2
èT
oppure un tipoNullable<T>
o un'interfaccia di base diT
. Ad esempio, nel frammento di codiceint? x = 3; if (x is int v) { /* code using v */ }
La condizione dell'istruzione
if
ètrue
in fase di esecuzione e la variabilev
contiene il valore3
di tipoint
all'interno del blocco. esempio finale
11.2.3 Modello costante
Un constant_pattern viene usato per testare il valore di un valore di input del modello (§11,1) rispetto al valore costante specificato.
constant_pattern
: constant_expression
;
Un criterio P
costante è applicabile a un tipo T
se è presente una conversione implicita dall'espressione costante di P
al tipo T
.
Per un criterio P
costante , il relativo valore convertito è
- se il tipo del valore di input del criterio è un tipo integrale o un tipo enumerazione, il valore costante del criterio convertito in tale tipo; altrimenti
- se il tipo del valore di input del criterio è la versione nullable di un tipo integrale o di un tipo enum, il valore costante del modello convertito nel tipo sottostante; altrimenti
- valore del valore costante del criterio.
Dato un valore di input del criterio e un criterio P
costante con valore convertito v,
- se e ha tipo integrale o enumerazione o una forma nullable di uno di questi e v ha un tipo integrale, il criterio
P
corrisponde al valore e se il risultato dell'espressionee == v
ètrue
; in caso contrario, - il criterio
P
corrisponde al valore e seobject.Equals(e, v)
restituiscetrue
.
Esempio: l'istruzione
switch
nel metodo seguente usa cinque modelli costanti nelle etichette case.static decimal GetGroupTicketPrice(int visitorCount) { switch (visitorCount) { case 1: return 12.0m; case 2: return 20.0m; case 3: return 27.0m; case 4: return 32.0m; case 0: return 0.0m; default: throw new ArgumentException(...); } }
esempio finale
11.2.4 Modello var
Un var_pattern corrisponde a ogni valore. Ovvero, un'operazione di corrispondenza dei criteri con un var_pattern ha sempre esito positivo.
Un var_pattern è applicabile a ogni tipo.
var_pattern
: 'var' designation
;
designation
: simple_designation
;
Dato un valore di input del criterio (§11.1) e, se la designazione è l'identificatore _
, indica un'eliminazione (§9.2.9.1) e il valore di e non è associato ad alcun elemento. Sebbene una variabile dichiarata con tale nome possa trovarsi nell'ambito in quel punto, tale variabile denominata non viene visualizzata in questo contesto. Se la designazione è qualsiasi altro identificatore, in fase di esecuzione il valore di e è associato a una variabile locale appena introdotta (§9.2.9) di tale nome il cui tipo è il tipo statico di e e e il valore di input del criterio viene assegnato a tale variabile locale.
Si tratta di un errore se il nome var
viene associato a un tipo in cui viene usato un var_pattern .
11.3 Subsumption pattern
In un'istruzione switch si verifica un errore se il modello di un case è sottosumato dal set precedente di case non sorvegliati (§13.8.3). In modo informale, ciò significa che qualsiasi valore di input sarebbe stato confrontato con uno dei casi precedenti. Le regole seguenti definiscono quando un set di modelli esegue il subsume di un determinato modello:
Un criterio P
corrisponde a una costante K
se la specifica per il comportamento di runtime del modello corrisponde P
a K
.
Un set di modelli Q
esegue il subsume di un modello P
se una delle condizioni seguenti contiene:
P
è un modello costante e uno dei modelli nel setQ
corrisponderebbeP
al valore convertitoP
è un criterio var e il set di modelliQ
è esaustivo (§11.4) per il tipo del valore di input del pattern (§11.1) e il valore di input del criterio non è di un tipo nullable o un criterio inQ
corrispondenull
a .P
è un modello di dichiarazione con tipoT
e il set di modelliQ
è esaustivo per il tipoT
(§11.4).
11.4 Esaustività dei criteri
In modo informale, un set di modelli è esaustivo per un tipo se, per ogni valore possibile di tale tipo diverso da Null, è applicabile un modello nel set. Le regole seguenti definiscono quando un set di modelli è esaustivo per un tipo:
Un set di modelli Q
è esaustivo per un tipo T
se una delle condizioni seguenti contiene:
T
è un tipo integrale o enumerazione o una versione nullable di uno di questi e per ogni valore possibile delT
tipo sottostante non nullable, alcuni criteri inQ
corrisponderebbero a tale valore; o- Un modello in
Q
è un modello var; o - Un modello in
Q
è un modello di dichiarazione per il tipoD
ed è presente una conversione di identità, una conversione di riferimento implicita o una conversione boxing daT
aD
.
Esempio:
static void M(byte b) { switch (b) { case 0: case 1: case 2: ... // handle every specific value of byte break; // error: the pattern 'byte other' is subsumed by the (exhaustive) // previous cases case byte other: break; } }
esempio finale
ECMA C# draft specification