Criteri di ricerca: le is
espressioni e switch
e gli operatori and
, or
e not
nei modelli
Usare l'espressione, l'istruzione switch e l'espressione switch per trovare una corrispondenza con un'espressione di input rispetto a un numero qualsiasi di caratteristiche.is
C# supporta più criteri, tra cui dichiarazione, tipo, costante, relazionale, proprietà, elenco, var e discard. I criteri possono essere combinati usando parole chiave della logica booleana and
, or
e not
.
Le espressioni e le istruzioni di C# seguenti supportano i criteri di ricerca:
In questi costrutti, è possibile associare un'espressione di input a uno dei criteri seguenti:
- Criterio di dichiarazione: per controllare il tipo di runtime di un'espressione e, se è presente una corrispondenza, assegnare un risultato dell'espressione a una variabile dichiarata.
- Tipo di criterio: per controllare il tipo di runtime di un'espressione.
- Modello costante: per verificare che il risultato di un'espressione sia uguale a una costante specificata.
- Criteri relazionali: per confrontare un risultato di espressione con una costante specificata.
- Modelli logici: per verificare che un'espressione corrisponda a una combinazione logica di modelli.
- Modello di proprietà: per verificare che le proprietà o i campi di un'espressione corrispondano a modelli annidati.
- Criterio posizionale: per decostruire un risultato dell'espressione e verificare se i valori risultanti corrispondono a modelli annidati.
- Criterio
var
: per trovare una corrispondenza con qualsiasi espressione e assegnarne il risultato a una variabile dichiarata. - Criterio discard: per trovare la corrispondenza con qualsiasi espressione.
- Modelli elenco: per verificare che una sequenza di elementi corrisponda ai modelli annidati corrispondenti. Introdotto in C# 11.
I criteri logico, proprietà, posizionale ed elenco sono criteri di ricorsivi. Ovvero, possono contenere criteri annidati.
Per un esempio su come usare questi criteri per creare un algoritmo basato sui dati, vedere Esercitazione: usare criteri di ricerca per creare algoritmi basati sui tipi e sui dati.
Criteri di dichiarazione e di tipo
È possibile usare modelli di dichiarazione e di tipo per verificare se il tipo di runtime di un'espressione è compatibile con un determinato tipo. Con un criterio di dichiarazione, è anche possibile dichiarare una nuova variabile locale. Quando un criterio di dichiarazione corrisponde a un'espressione, a tale variabile viene assegnato un risultato di espressione convertita, come illustrato nell'esempio seguente:
object greeting = "Hello, World!";
if (greeting is string message)
{
Console.WriteLine(message.ToLower()); // output: hello, world!
}
Un criterio di dichiarazione con tipo T
corrisponde a un'espressione quando un risultato di un'espressione è diverso da Null e una delle condizioni seguenti è vera:
Il tipo di runtime di un risultato dell'espressione è
T
.Il tipo di runtime di un risultato di un'espressione deriva dal tipo
T
, implementa l'interfacciaT
o esiste un'altra conversione di riferimento implicita da essa aT
. L'esempio seguente illustra due casi in cui questa condizione è True:var numbers = new int[] { 10, 20, 30 }; Console.WriteLine(GetSourceLabel(numbers)); // output: 1 var letters = new List<char> { 'a', 'b', 'c', 'd' }; Console.WriteLine(GetSourceLabel(letters)); // output: 2 static int GetSourceLabel<T>(IEnumerable<T> source) => source switch { Array array => 1, ICollection<T> collection => 2, _ => 3, };
Nell'esempio precedente, alla prima chiamata al
GetSourceLabel
metodo, il primo criterio corrisponde a un valore di argomento perché il tipo di runtime dell'argomentoint[]
deriva dal tipo Array. Nella seconda chiamata al metodoGetSourceLabel
, il tipo di runtime dell'argomento List<T> non deriva dal tipo Array ma implementa l'interfaccia ICollection<T>.Il tipo di runtime del risultato di un'espressione è un tipo valore nullable con il tipo sottostante
T
.Esiste una conversione boxing o unboxing dal tipo di run-time del risultato di un'espressione al tipo
T
.
L'esempio seguente illustra le ultime due condizioni:
int? xNullable = 7;
int y = 23;
object yBoxed = y;
if (xNullable is int a && yBoxed is int b)
{
Console.WriteLine(a + b); // output: 30
}
Se si vuole controllare solo il tipo di un'espressione, occorre usare un'istruzione discard _
al posto del nome di una variabile, come illustrato nell'esempio seguente:
public abstract class Vehicle {}
public class Car : Vehicle {}
public class Truck : Vehicle {}
public static class TollCalculator
{
public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
{
Car _ => 2.00m,
Truck _ => 7.50m,
null => throw new ArgumentNullException(nameof(vehicle)),
_ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
};
}
A tale scopo, è possibile usare un criterio di tipo, come illustrato nell'esempio seguente:
public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch
{
Car => 2.00m,
Truck => 7.50m,
null => throw new ArgumentNullException(nameof(vehicle)),
_ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)),
};
Analogamente a un criterio di dichiarazione, un criterio di tipo corrisponde a un'espressione quando un risultato di espressione è diverso da Null e il tipo di runtime soddisfa una qualsiasi delle condizioni precedenti.
Per verificare la presenza di valori non Null, è possibile usare un criterio costante null
negato, come illustrato nell'esempio seguente:
if (input is not null)
{
// ...
}
Per altre informazioni, vedere le sezioni Criterio di dichiarazione e Criterio di tipo delle note sulla proposta di funzionalità.
Criterio costante
Si usa un criterio costante per verificare se il risultato di un'espressione è uguale a una costante specificata, come illustrato nell'esempio seguente:
public static decimal GetGroupTicketPrice(int visitorCount) => visitorCount switch
{
1 => 12.0m,
2 => 20.0m,
3 => 27.0m,
4 => 32.0m,
0 => 0.0m,
_ => throw new ArgumentException($"Not supported number of visitors: {visitorCount}", nameof(visitorCount)),
};
In un criterio costante, è possibile usare qualsiasi espressione costante, ad esempio:
- un valore letterale numerico integer o a virgola mobile
- un char
- un valore letterale stringa.
- un valore booleano
true
ofalse
- un valore enum
- nome di un campo dichiarato o locale const dichiarato
null
L'espressione deve essere un tipo convertibile nel tipo costante, con un'eccezione: un'espressione il cui tipo è Span<char>
o ReadOnlySpan<char>
può essere confrontata con stringhe costanti in C# 11 e versioni successive.
Usare un criterio costante per verificare la presenza di null
, come illustrato nell'esempio seguente:
if (input is null)
{
return;
}
Il compilatore garantisce che non venga richiamato alcun operatore di uguaglianza di overload dall'utente ==
quando viene valutata l'espressione x is null
.
È possibile usare un criterio costante negato null
per verificare la presenza di valori diversi da Null, come illustrato nell'esempio seguente:
if (input is not null)
{
// ...
}
Per altre informazioni, vedere la sezione criterio costante della nota sulla proposta di funzionalità.
Criteri relazionali
Si usa un criterio relazionale per confrontare il risultato di un'espressione con una costante, come illustrato nell'esempio seguente:
Console.WriteLine(Classify(13)); // output: Too high
Console.WriteLine(Classify(double.NaN)); // output: Unknown
Console.WriteLine(Classify(2.4)); // output: Acceptable
static string Classify(double measurement) => measurement switch
{
< -4.0 => "Too low",
> 10.0 => "Too high",
double.NaN => "Unknown",
_ => "Acceptable",
};
In un criterio relazionale è possibile usare uno qualsiasi degli operatori relazionali <
, >
, <=
o >=
. La parte destra di un criterio relazionale deve essere un'espressione costante. L'espressione costante può essere di tipo integer, a virgola mobile, char o enumerazione.
Per verificare se un risultato di un'espressione è in un determinato intervallo, trovare la corrispondenza con un criterio and
congiuntivo, come illustrato nell'esempio seguente:
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 3, 14))); // output: spring
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 7, 19))); // output: summer
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 2, 17))); // output: winter
static string GetCalendarSeason(DateTime date) => date.Month switch
{
>= 3 and < 6 => "spring",
>= 6 and < 9 => "summer",
>= 9 and < 12 => "autumn",
12 or (>= 1 and < 3) => "winter",
_ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."),
};
Se il risultato di un'espressione è null
o non riesce a eseguire la conversione nel tipo di una costante per una conversione nullable o unboxing, un criterio relazionale non corrisponde a un'espressione.
Per altre informazioni, vedere la sezione Criteri relazionali della nota sulla proposta di funzionalità.
Criteri logici
Per creare i not
criteri logiciand
seguenti, è possibile usare i combinatori di criteri or
, e :
Criterio Negazione
not
che corrisponde a un'espressione quando il criterio negato non corrisponde all'espressione. Nell'esempio seguente viene illustrato come negare un criterio costantenull
per verificare se un'espressione non è Null:if (input is not null) { // ... }
Criterio congiuntivo
and
che corrisponde a un'espressione quando entrambi i criteri corrispondono all'espressione. L'esempio seguente illustra come combinare criteri relazionali per verificare se un valore si trova in un determinato intervallo:Console.WriteLine(Classify(13)); // output: High Console.WriteLine(Classify(-100)); // output: Too low Console.WriteLine(Classify(5.7)); // output: Acceptable static string Classify(double measurement) => measurement switch { < -40.0 => "Too low", >= -40.0 and < 0 => "Low", >= 0 and < 10.0 => "Acceptable", >= 10.0 and < 20.0 => "High", >= 20.0 => "Too high", double.NaN => "Unknown", };
Criterio disgiuntivo
or
che corrisponde a un'espressione quando uno dei due criteri corrisponde all'espressione, come illustrato nell'esempio seguente:Console.WriteLine(GetCalendarSeason(new DateTime(2021, 1, 19))); // output: winter Console.WriteLine(GetCalendarSeason(new DateTime(2021, 10, 9))); // output: autumn Console.WriteLine(GetCalendarSeason(new DateTime(2021, 5, 11))); // output: spring static string GetCalendarSeason(DateTime date) => date.Month switch { 3 or 4 or 5 => "spring", 6 or 7 or 8 => "summer", 9 or 10 or 11 => "autumn", 12 or 1 or 2 => "winter", _ => throw new ArgumentOutOfRangeException(nameof(date), $"Date with unexpected month: {date.Month}."), };
Come illustrato nell'esempio precedente, è possibile usare ripetutamente i combinatori di criteri in un criterio.
Priorità e ordine di controllo
I combinatori di criteri vengono ordinati in base all'ordine di associazione delle espressioni come indicato di seguito:
not
and
or
Il not
criterio viene associato prima al relativo operando. Il and
criterio viene associato dopo qualsiasi not
associazione di espressioni di pattern. Il or
criterio viene associato a tutti i not
modelli e and
agli operandi. Nell'esempio seguente viene eseguito un tentativo di corrispondenza con tutti i caratteri che non sono lettere minuscole, a
- z
. Si verifica un errore, perché il not
criterio viene associato prima del and
modello:
// Incorrect pattern. `not` binds before `and`
static bool IsNotLowerCaseLetter(char c) => c is not >= 'a' and <= 'z';
L'associazione predefinita indica che l'esempio precedente viene analizzato come nell'esempio seguente:
// The default binding without parentheses is shows in this method. `not` binds before `and`
static bool IsNotLowerCaseLetterDefaultBinding(char c) => c is ((not >= 'a') and <= 'z');
Per correggerlo, è necessario specificare che si vuole not
associare all'espressione >= 'a' and <= 'z'
:
// Correct pattern. Force `and` before `not`
static bool IsNotLowerCaseLetterParentheses(char c) => c is not (>= 'a' and <= 'z');
L'aggiunta di parentesi diventa più importante man mano che i modelli diventano più complessi. In generale, usare le parentesi per chiarire i modelli per altri sviluppatori, come illustrato nell'esempio seguente:
static bool IsLetter(char c) => c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z');
Nota
L'ordine in cui i modelli con lo stesso ordine di associazione vengono controllati non è definito. In fase di esecuzione, è possibile controllare prima i modelli annidati a destra di più or
modelli e più and
modelli.
Per altre informazioni, vedere la sezione Combinatori costanti della nota sulla proposta di funzionalità.
Criterio di proprietà
Si usa un criterio di proprietà per trovare una corrispondenza con le proprietà o i campi di un'espressione rispetto ai criteri annidati, come illustrato nell'esempio seguente:
static bool IsConferenceDay(DateTime date) => date is { Year: 2020, Month: 5, Day: 19 or 20 or 21 };
Un criterio di proprietà corrisponde a un'espressione quando il risultato di un'espressione è diverso da Null e ogni criterio annidato corrisponde alla proprietà o al campo corrispondente del risultato dell'espressione.
È anche possibile aggiungere un controllo del tipo di runtime e una dichiarazione di variabile a un criterio di proprietà, come illustrato nell'esempio seguente:
Console.WriteLine(TakeFive("Hello, world!")); // output: Hello
Console.WriteLine(TakeFive("Hi!")); // output: Hi!
Console.WriteLine(TakeFive(new[] { '1', '2', '3', '4', '5', '6', '7' })); // output: 12345
Console.WriteLine(TakeFive(new[] { 'a', 'b', 'c' })); // output: abc
static string TakeFive(object input) => input switch
{
string { Length: >= 5 } s => s.Substring(0, 5),
string s => s,
ICollection<char> { Count: >= 5 } symbols => new string(symbols.Take(5).ToArray()),
ICollection<char> symbols => new string(symbols.ToArray()),
null => throw new ArgumentNullException(nameof(input)),
_ => throw new ArgumentException("Not supported input type."),
};
Un criterio di proprietà è un criterio ricorsivo. Ovvero, è possibile usare qualsiasi criterio come criterio annidato. È possibile usare un criterio di proprietà per associare parti di dati a criteri annidati, come illustrato nell'esempio seguente:
public record Point(int X, int Y);
public record Segment(Point Start, Point End);
static bool IsAnyEndOnXAxis(Segment segment) =>
segment is { Start: { Y: 0 } } or { End: { Y: 0 } };
Nell'esempio precedente vengono utilizzati combinatori di criteri or
e tipi di record.
A partire da C# 10, è possibile fare riferimento a proprietà o campi annidati all'interno di un criterio di proprietà. Questa funzionalità è nota come criterio di proprietà esteso. Ad esempio, è possibile effettuare il refactoring del metodo dall'esempio precedente nel codice equivalente seguente:
static bool IsAnyEndOnXAxis(Segment segment) =>
segment is { Start.Y: 0 } or { End.Y: 0 };
Per altre informazioni, vedere la sezione Criterio di proprietà della nota sulla proposta di funzionalità e la nota sulla proposta di funzionalità Criteri di proprietà estesi.
Suggerimento
È possibile usare la regola di stile Semplificare il criterio di proprietà (IDE0170) per migliorare la leggibilità del codice suggerendo posizioni in cui usare criteri di proprietà estesi.
Criterio posizionale
Si usa un criterio posizionale per decostruire il risultato di un'espressione e trovare una corrispondenza con i valori risultanti rispetto ai criteri annidati corrispondenti, come illustrato nell'esempio seguente:
public readonly struct Point
{
public int X { get; }
public int Y { get; }
public Point(int x, int y) => (X, Y) = (x, y);
public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
}
static string Classify(Point point) => point switch
{
(0, 0) => "Origin",
(1, 0) => "positive X basis end",
(0, 1) => "positive Y basis end",
_ => "Just a point",
};
Nell'esempio precedente, il tipo di un'espressione contiene il criterio Deconstruct, che viene usato per decostruire il risultato di un'espressione.
Importante
L'ordine dei membri nei criteri per la posizione deve corrispondere all'ordine dei parametri nel metodo Deconstruct
. Questo perché il codice generato per i criteri per la posizione chiama il metodo Deconstruct
.
È anche possibile associare espressioni di tipi tupla a criteri posizionali. In questo modo, è possibile associare più input a vari criteri, come illustrato nell'esempio seguente:
static decimal GetGroupTicketPriceDiscount(int groupSize, DateTime visitDate)
=> (groupSize, visitDate.DayOfWeek) switch
{
(<= 0, _) => throw new ArgumentException("Group size must be positive."),
(_, DayOfWeek.Saturday or DayOfWeek.Sunday) => 0.0m,
(>= 5 and < 10, DayOfWeek.Monday) => 20.0m,
(>= 10, DayOfWeek.Monday) => 30.0m,
(>= 5 and < 10, _) => 12.0m,
(>= 10, _) => 15.0m,
_ => 0.0m,
};
Nell'esempio precedente vengono usati criteri relazionali e logici.
È possibile usare i nomi degli elementi della tupla e il parametro Deconstruct
in un criterio posizionale, come illustrato nell'esempio seguente:
var numbers = new List<int> { 1, 2, 3 };
if (SumAndCount(numbers) is (Sum: var sum, Count: > 0))
{
Console.WriteLine($"Sum of [{string.Join(" ", numbers)}] is {sum}"); // output: Sum of [1 2 3] is 6
}
static (double Sum, int Count) SumAndCount(IEnumerable<int> numbers)
{
int sum = 0;
int count = 0;
foreach (int number in numbers)
{
sum += number;
count++;
}
return (sum, count);
}
È anche possibile estendere un criterio posizionale in uno dei modi seguenti:
Aggiungere un controllo del tipo di runtime e una dichiarazione di variabile, come illustrato nell'esempio seguente:
public record Point2D(int X, int Y); public record Point3D(int X, int Y, int Z); static string PrintIfAllCoordinatesArePositive(object point) => point switch { Point2D (> 0, > 0) p => p.ToString(), Point3D (> 0, > 0, > 0) p => p.ToString(), _ => string.Empty, };
Nell'esempio precedente vengono utilizzati record posizionali che forniscono in modo implicito il metodo
Deconstruct
.È possibile usare un criterio di proprietà all'interno di un criterio posizionale, come illustrato nell'esempio seguente:
public record WeightedPoint(int X, int Y) { public double Weight { get; set; } } static bool IsInDomain(WeightedPoint point) => point is (>= 0, >= 0) { Weight: >= 0.0 };
Combinare due utilizzi precedenti, come illustrato nell'esempio seguente:
if (input is WeightedPoint (> 0, > 0) { Weight: > 0.0 } p) { // .. }
Un criterio posizionale è un criterio ricorsivo. Ovvero, è possibile usare qualsiasi criterio come criterio annidato.
Per altre informazioni, vedere la sezione Criterio posizionale della nota sulla proposta di funzionalità.
Criterio var
È possibile usare un criterio var
per trovare una corrispondenza con qualsiasi espressione, inclusa null
, e assegnarne il risultato a una nuova variabile locale, come illustrato nell'esempio seguente:
static bool IsAcceptable(int id, int absLimit) =>
SimulateDataFetch(id) is var results
&& results.Min() >= -absLimit
&& results.Max() <= absLimit;
static int[] SimulateDataFetch(int id)
{
var rand = new Random();
return Enumerable
.Range(start: 0, count: 5)
.Select(s => rand.Next(minValue: -10, maxValue: 11))
.ToArray();
}
Un criterio var
è utile quando è necessaria una variabile temporanea all'interno di un'espressione booleana per contenere il risultato dei calcoli intermedi. È anche possibile usare un criterio var
quando è necessario eseguire più controlli in caso di guard when
di un'espressione o di un'istruzione switch
, come illustrato nell'esempio seguente:
public record Point(int X, int Y);
static Point Transform(Point point) => point switch
{
var (x, y) when x < y => new Point(-x, y),
var (x, y) when x > y => new Point(x, -y),
var (x, y) => new Point(x, y),
};
static void TestTransform()
{
Console.WriteLine(Transform(new Point(1, 2))); // output: Point { X = -1, Y = 2 }
Console.WriteLine(Transform(new Point(5, 2))); // output: Point { X = 5, Y = -2 }
}
Nell'esempio precedente, il criterio var (x, y)
equivale a un criterio posizionale (var x, var y)
.
In un criterio var
, il tipo di una variabile dichiarata è il tipo in fase di compilazione dell'espressione corrispondente al criterio.
Per altre informazioni, vedere la sezione criterio Var della nota sulla proposta di funzionalità.
Criterio discard
Per trovare una corrispondenza con qualsiasi espressione, inclusa null
, si usa un criterio discard _
, come illustrato nell'esempio seguente:
Console.WriteLine(GetDiscountInPercent(DayOfWeek.Friday)); // output: 5.0
Console.WriteLine(GetDiscountInPercent(null)); // output: 0.0
Console.WriteLine(GetDiscountInPercent((DayOfWeek)10)); // output: 0.0
static decimal GetDiscountInPercent(DayOfWeek? dayOfWeek) => dayOfWeek switch
{
DayOfWeek.Monday => 0.5m,
DayOfWeek.Tuesday => 12.5m,
DayOfWeek.Wednesday => 7.5m,
DayOfWeek.Thursday => 12.5m,
DayOfWeek.Friday => 5.0m,
DayOfWeek.Saturday => 2.5m,
DayOfWeek.Sunday => 2.0m,
_ => 0.0m,
};
Nell'esempio precedente viene usato un criterio discard per gestire null
e qualsiasi valore intero che non ha il membro corrispondente dell'enumerazione DayOfWeek. Ciò garantisce che un'espressione switch
nell'esempio gestisca tutti i possibili valori di input. Se non si usa un criterio di discard in un'espressione switch
e nessuno dei criteri dell'espressione corrisponde a un input, il runtime genera un'eccezione. Il compilatore genera un avviso se un'espressione switch
non gestisce tutti i possibili valori di input.
Un criterio di discard non può essere un criterio in un'espressione is
o un'istruzione switch
. In questi casi, per trovare una corrispondenza con qualsiasi espressione, usare un var
criterio con un oggetto discard: var _
. Un criterio discard può essere il criterio in un'espressione switch
.
Per altre informazioni, vedere la sezione Criterio discard della nota sulla proposta di funzionalità.
Criterio tra parentesi
È possibile inserire parentesi intorno a qualsiasi criterio. In genere, è necessario sottolineare o modificare la priorità nei criteri logici, come illustrato nell'esempio seguente:
if (input is not (float or double))
{
return;
}
Criteri elenco
A partire da C# 11, è possibile associare una matrice o un elenco a una sequenza di criteri, come illustrato nell'esempio seguente:
int[] numbers = { 1, 2, 3 };
Console.WriteLine(numbers is [1, 2, 3]); // True
Console.WriteLine(numbers is [1, 2, 4]); // False
Console.WriteLine(numbers is [1, 2, 3, 4]); // False
Console.WriteLine(numbers is [0 or 1, <= 2, >= 3]); // True
Come illustrato nell'esempio precedente, un criterio di elenco viene confrontato quando ogni criterio annidato corrisponde all'elemento corrispondente di una sequenza di input. È possibile usare qualsiasi criterio all'interno di un criterio di elenco. Per trovare una corrispondenza con qualsiasi elemento, usare il criterio discard o, se si vuole acquisire anche l'elemento, il criterio var, come illustrato nell'esempio seguente:
List<int> numbers = new() { 1, 2, 3 };
if (numbers is [var first, _, _])
{
Console.WriteLine($"The first element of a three-item list is {first}.");
}
// Output:
// The first element of a three-item list is 1.
Gli esempi precedenti corrispondono a un'intera sequenza di input rispetto a un criterio di elenco. Per trovare la corrispondenza degli elementi solo all'inizio o/e alla fine di una sequenza di input, usare il criterio di sezione ..
, come illustrato nell'esempio seguente:
Console.WriteLine(new[] { 1, 2, 3, 4, 5 } is [> 0, > 0, ..]); // True
Console.WriteLine(new[] { 1, 1 } is [_, _, ..]); // True
Console.WriteLine(new[] { 0, 1, 2, 3, 4 } is [> 0, > 0, ..]); // False
Console.WriteLine(new[] { 1 } is [1, 2, ..]); // False
Console.WriteLine(new[] { 1, 2, 3, 4 } is [.., > 0, > 0]); // True
Console.WriteLine(new[] { 2, 4 } is [.., > 0, 2, 4]); // False
Console.WriteLine(new[] { 2, 4 } is [.., 2, 4]); // True
Console.WriteLine(new[] { 1, 2, 3, 4 } is [>= 0, .., 2 or 4]); // True
Console.WriteLine(new[] { 1, 0, 0, 1 } is [1, 0, .., 0, 1]); // True
Console.WriteLine(new[] { 1, 0, 1 } is [1, 0, .., 0, 1]); // False
Un criterio di sezione corrisponde a zero o più elementi. È possibile usare al massimo un criterio di sezione in un criterio di elenco. Il criterio di sezione può essere visualizzato solo in un criterio di elenco.
È anche possibile annidare un criterio secondario all'interno di un criterio di sezione, come illustrato nell'esempio seguente:
void MatchMessage(string message)
{
var result = message is ['a' or 'A', .. var s, 'a' or 'A']
? $"Message {message} matches; inner part is {s}."
: $"Message {message} doesn't match.";
Console.WriteLine(result);
}
MatchMessage("aBBA"); // output: Message aBBA matches; inner part is BB.
MatchMessage("apron"); // output: Message apron doesn't match.
void Validate(int[] numbers)
{
var result = numbers is [< 0, .. { Length: 2 or 4 }, > 0] ? "valid" : "not valid";
Console.WriteLine(result);
}
Validate(new[] { -1, 0, 1 }); // output: not valid
Validate(new[] { -1, 0, 0, 1 }); // output: valid
Per altre informazioni, vedere la nota relativa alla proposta di funzionalità Criteri di elenco.
Specifiche del linguaggio C#
Per altre informazioni, vedere la sezione Criteri and criteri di ricerca della Specifica del linguaggio C#.
Per informazioni sulle funzionalità aggiunte in C# 8 e versioni successive, vedere le note sulla proposta delle funzionalità seguenti:
- Criteri di ricerca ricorsivi
- Aggiornamenti dei criteri di ricerca
- C# 10 - Criteri di proprietà estesi
- C# 11 -Criteri di elenco
- C# 11 - Criteri di ricerca
Span<char>
in base al valore letterale stringa