11 Vzory a porovnávání vzorů

11.1 Obecné

Vzor je syntaktická forma, kterou lze použít s operátorem is (§12.15.12) v switch_statement (§13.8.3) a v switch_expression (§12.12) vyjádřit tvar dat, s nímž se mají porovnávat příchozí data. Vzory můžou být rekurzivní, takže se části dat můžou shodovat s dílčími vzory.

Model se testuje s hodnotou v řadě kontextů:

  • V příkazu switch se vzor popisku případu testuje s výrazem příkazu switch.
  • V operátoru is-pattern je vzor na pravé straně testován proti výrazu vlevo.
  • Ve výrazu switch se vzorswitch_expression_arm testuje s výrazem na levé straně výrazu switch-expression.
  • V vnořených kontextech se dílčí vzor testuje na základě hodnot načtených z vlastností, polí nebo indexovaných z jiných vstupních hodnot v závislosti na formuláři vzoru.

Hodnota, proti které se testuje, se nazývá vstupní hodnota vzoru.

11.2 Vzorové formuláře

11.2.1 Obecné

Vzor může mít jednu z následujících forem:

pattern
    : logical_pattern
    ;

primary_pattern
    : parenthesized_pattern
    | declaration_pattern
    | constant_pattern
    | var_pattern
    | positional_pattern
    | property_pattern
    | discard_pattern
    | type_pattern
    | relational_pattern
    ;

parenthesized_pattern
    : '(' pattern ')'
    ;

V produkčním '(' pattern ')' prostředí je možné model uzavřít do závorek, aby bylo možné vynutit pořadí vyhodnocení mezi vzory zkombinovaným pomocí jednoho z logical_patterns.

Některé vzorymůžou vést k deklaraci místní proměnné.

Každý formulář vzoru definuje sadu typů pro vstupní hodnoty, na které lze vzor použít. Vzor P se vztahuje na typ T , pokud T patří mezi typy, jejichž hodnoty se vzor může shodovat. Jedná se o chybu v době kompilace, pokud se v programu objeví vzorP, který odpovídá vstupní hodnotě vzoru (§11.1 pokud T není použitelný pro P.

Příklad: Následující příklad vygeneruje chybu v době kompilace, protože typ v kompilace je TextReader. Proměnná typu TextReader nemůže mít nikdy hodnotu, která je kompatibilní s string:

TextReader v = Console.In; // compile-time type of 'v' is 'TextReader'
if (v is string) // compile-time error
{
    // code assuming v is a string
}

Následující však nevygeneruje chybu v době kompilace, protože typ v kompilace je object. Proměnná typu object může mít hodnotu, která je kompatibilní s string:

object v = Console.In;
if (v is string s)
{
    // code assuming v is a string
}

konec příkladu

Každý formulář vzoru definuje sadu hodnot, pro které vzor odpovídá hodnotě za běhu.

Pořadí vyhodnocení operací a vedlejších účinků během porovnávání vzorů (volání Deconstruct, přístupů k vlastnostem a vyvolání metod v System.ITuple) není zadáno.

11.2.2 Model deklarace

Declaration_pattern slouží k otestování, že hodnota má daný typ, a pokud je test úspěšný, volitelně zadat hodnotu v proměnné tohoto typu.

declaration_pattern
    : type simple_designation
    ;
simple_designation
    : discard_designation
    | single_variable_designation
    ;
discard_designation
    : '_'
    ;
single_variable_designation
    : identifier
    ;

Simple_designation s tokenem _ se považuje za discard_designation, nikoli single_variable_designation.

Typ modulu runtime hodnoty se testuje s typem ve vzoru pomocí stejných pravidel uvedených v operátoru is-type (§12.15.12.1). Pokud je test úspěšný, vzor odpovídá této hodnotě. Jedná se o chybu v době kompilace, pokud je typ hodnoty null (§8.3.12) nebo odkazový typ s možnou hodnotou null (§8.9.3). Tento vzorový formulář nikdy neodpovídá hodnotě null .

Poznámka: Výraz is-type e is T a vzor e is T _ deklarace jsou ekvivalentní, pokud T není typu s možnou hodnotou null. koncová poznámka

Při zadání vzorové vstupní hodnoty (§11.1) e, pokud je simple_designationdiscard_designation, označuje zahození (§9.2.9.2) a hodnota e není nijak vázána. (I když deklarovaná proměnná s názvem _ může být v tomto okamžiku v oboru, tato pojmenovaná proměnná se v tomto kontextu nezobrazí.) Pokud je simple_designationsingle_variable_designation, zanese se místní proměnná (§9.2.9) daného typu pojmenovaného daným identifikátorem. Tato místní proměnná má přiřazenou hodnotu vstupní hodnoty vzoru, pokud vzor odpovídá hodnotě.

Určité kombinace statického typu vstupní hodnoty vzoru a daného typu jsou považovány za nekompatibilní a výsledkem chyby v době kompilace. Hodnota statického typu E je oznamována jako vzor kompatibilní s typem T , pokud existuje převod identity, implicitní nebo explicitní převod odkazu, převod boxingu, převod rozbalení nebo implicitní nebo explicitní převod typu hodnoty null z E na T, nebo je-li otevřený ET typ (§8.4.3). Deklarace vzoru pojmenování typu T je použitelná pro každý typ E , pro který E je vzor kompatibilní s T.

Poznámka: Podpora otevřených typů může být nejužitečnější při kontrole typů, které mohou být buď struktury, nebo typy tříd, a boxování je třeba se vyhnout. koncová poznámka

Příklad: Model deklarace je užitečný pro provádění testů typů běhu referenčních typů a nahrazuje idiom.

var v = expr as Type;
if (v != null) { /* code using v */ }

s mírně stručnější

if (expr is Type v) { /* code using v */ }

konec příkladu

Příklad: Vzor deklarace lze použít k otestování hodnot typů s možnou hodnotou null: hodnota typu (nebo boxedNullable<T>) odpovídá vzoru TT2 id typu, pokud hodnota není null a T2 je T, nebo některé základního typu nebo rozhraní T. Například v fragmentu kódu

int? x = 3;
if (x is int v) { /* code using v */ }

Podmínka if příkazu je true za běhu a proměnná v obsahuje hodnotu 3 typu int uvnitř bloku. Po bloku je proměnná v v oboru, ale rozhodně není přiřazena. konec příkladu

11.2.3 Konstantní vzor

Constant_pattern se používá k otestování hodnoty vstupní hodnoty vzoru (§11.1) s danou konstantní hodnotou.

constant_pattern
    : constant_expression
    ;

Konstantní vzor P se vztahuje na typ T , pokud existuje implicitní převod z konstantního výrazu P na typ T.

U konstantního vzoru Pje převedená hodnota

  • je-li typ vstupní hodnoty vzoru celočíselný typ nebo výčtový typ, konstantní hodnota vzoru převedena na tento typ; jinak
  • pokud typ vstupní hodnoty vzoru je nullable verze celočíselného typu nebo výčtu typ, konstantní hodnota vzoru převedena na jeho základní typ; jinak
  • hodnota konstantní hodnoty vzoru.

Při zadání vstupní hodnoty vzoru e a konstantního vzoru P s převedenou hodnotou v,

  • pokud e má celočíselný typ nebo výčtový typ nebo nulovou formu jednoho z nich a v má celočíselný typ, vzor Podpovídá hodnotě e, pokud je e == vvýsledek výrazu true ;
  • vzor P odpovídá hodnotě e, pokud se vrátí object.Equals(e, v).true

Příklad: Příkaz switch v následující metodě používá pět konstantních vzorů v popiscích písmen.

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(...);
    }
}

konec příkladu

11.2.4 Vzor var

Var_pattern odpovídá každé hodnotě. To znamená, že operace porovnávání vzorů s var_pattern vždy proběhne úspěšně.

Var_pattern platí pro každý typ.

var_pattern
    : 'var' designation
    ;
designation
    : simple_designation
    | tuple_designation
    ;
tuple_designation
    : '(' designations? ')'
    ;
designations
    : designation (',' designation)*
    ;

Při zadání vzorové vstupní hodnoty (§11.1) e, pokud je označenídiscard_designation, označuje zahození (§9.2.9.2) a hodnota e není vázána na nic. (I když deklarovaná proměnná s tímto názvem může být v tomto okamžiku v oboru, tato pojmenovaná proměnná se v tomto kontextu nezobrazí.) V opačném případě, pokud je označenísingle_variable_designation, je hodnota e vázána na nově zavedenou místní proměnnou (§9.2.9) tohoto názvu, jehož typ je statickým typem e, a vstupní hodnota vzoru je přiřazena k této místní proměnné.

Jedná se o chybu, pokud by se název var sváže s typem, ve kterém se používá var_pattern .

Je-li označenítuple_designation, je vzor ekvivalentní positional_pattern (§11.2.5) (var formuláře, ... ) kde jsou označenínalezena v tuple_designation. Například vzor var (x, (y, z)) je ekvivalentní (var x, (var y, var z)).

11.2.5 Poziční vzor

Positional_pattern zkontroluje, zda vstupní hodnota není null, vyvolá odpovídající Deconstruct metodu (§12.7) a provede další porovnávání vzorů s výslednými hodnotami. Podporuje také syntaxi vzoru řazenou kolekci členů (bez zadaného typu), pokud je typ vstupní hodnoty stejný jako typ obsahující Deconstruct, nebo pokud typ vstupní hodnoty je typ řazené kolekce členů, nebo pokud typ vstupní hodnoty je object nebo System.ITuple a typ modulu runtime výraz implementuje System.ITuple.

positional_pattern
    : type? '(' subpatterns? ')' property_subpattern? simple_designation?
    ;
subpatterns
    : subpattern (',' subpattern)*
    ;
subpattern
    : pattern
    | subpattern_name ':' pattern
    ;
subpattern_name
    : identifier
    | subpattern_name '.' identifier
    ;

Vzhledem k porovnání vstupní hodnoty spodpatterny(typu) vzoru je metoda vybrána tak, že vyhledá v typu přístupné deklarace Deconstruct a vybere jednu z nich pomocí stejných pravidel jako pro dekonstrukční deklaraci. Jedná se o chybu, pokud positional_pattern vynechá typ, má jeden podpattern bez identifikátoru, nemá žádné property_subpattern a nemá žádné simple_designation. To se nejednoznačným způsobem liší mezi constant_pattern , která je závorka a positional_pattern. Chcete-li extrahovat hodnoty, které se mají shodovat se vzory v seznamu,

  • Pokud je typ vynechán a typ vstupního výrazu je typ řazené kolekce členů, bude počet podpatternů stejný jako kardinalita řazené kolekce členů. Každý prvek řazené kolekce členů se porovná s odpovídajícím podpatternem a shoda bude úspěšná, pokud všechny tyto prvky proběhnou úspěšně. Pokud má některý podpatternidentifikátor, pak tento výraz pojmenuje prvek řazené kolekce členů na odpovídající pozici v typu řazené kolekce členů.
  • Jinak, pokud vhodný Deconstruct existuje jako člen typu, jedná se o chybu v době kompilace, pokud typ vstupní hodnoty není kompatibilní s typem. Za běhu se vstupní hodnota testuje proti typu. Pokud se to nezdaří, shoda pozičního vzoru selže. Pokud bude úspěšné, vstupní hodnota se převede na tento typ a Deconstruct vyvolá se s čerstvými proměnnými generovanými kompilátorem pro příjem výstupních parametrů. Každá přijatá hodnota se shoduje s odpovídajícím podpatternem a shoda proběhne úspěšně, pokud jsou všechny tyto hodnoty úspěšné. Pokud má některý dílčí podpatternidentifikátor, pak tento parametr pojmenuje na odpovídající pozici Deconstruct.
  • V opačném případě, pokud je typ vynechán a vstupní hodnota je typu object nebo určitý typ, který lze převést System.ITuple na implicitní převod odkazu, a žádný identifikátor se nezobrazí mezi podpatterny, pak shoda použije System.ITuple.
  • V opačném případě se jedná o chybu v době kompilace.

Pořadí, ve kterém se podpatterny shodují za běhu, není zadáno a neúspěšná shoda se nemusí pokusit spárovat všechny podpatterny.

Příklad: Tady dekonstruujeme výsledek výrazu a porovnáme výsledné hodnoty s odpovídajícími vnořenými vzory:

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",
};

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);
}

konec příkladu

Příklad: Názvy elementů řazené kolekce členů a parametry dekonstrukce lze použít v pozičním vzoru následujícím způsobem:

var numbers = new List<int> { 10, 20, 30 };
if (SumAndCount(numbers) is (Sum: var sum, Count: var count))
{
    Console.WriteLine($"Sum of [{string.Join(" ", numbers)}] is {sum}");
}

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);
}

Výstup je vytvořen.

Sum of [10 20 30] is 60

konec příkladu

11.2.6 Vzor vlastností

Property_pattern zkontroluje, že vstupní hodnota není null, a rekurzivně odpovídá hodnotám extrahovaným použitím přístupných vlastností nebo polí.

property_pattern
    : type? property_subpattern simple_designation?
    ;
property_subpattern
    : '{' '}'
    | '{' subpatterns ','? '}'
    ;

Jedná se o chybu, pokud některý podpatternproperty_pattern neobsahuje subpattern_name.

Jedná se o chybu v době kompilace, pokud je typ hodnoty null (§8.3.12) nebo odkazový typ s možnou hodnotou null (§8.9.3).

Poznámka: Vzor kontroly hodnoty null se nevyučuje ze vzoru triviální vlastnosti. Pokud chcete zkontrolovat, jestli je řetězec s nenulový, můžete napsat některý z následujících formulářů:

#nullable enable
string s = "abc";
if (s is object o) ...  // o is of type object
if (s is string x1) ... // x1 is of type string
if (s is {} x2) ...     // x2 is of type string
if (s is {}) ...

koncová poznámka

Vzhledem k tomu, že výraz e odpovídápodpatternům{typu} vzoru, jedná se o chybu v době kompilace, pokud výraz e není kompatibilní se typem T určeným typem. Pokud typ chybí, předpokládá se, že se jedná o statický typ e. Každá subpattern_name , která se objeví na levé straně podpatternů , určí přístupnou čitelnou vlastnost nebo pole T. Pokud existuje simple_designationproperty_pattern , deklaruje proměnnou vzoru typu T.

Za běhu se výraz testuje proti T. Pokud se to nezdaří, vzor vlastnosti se nezdaří a výsledek je false. Pokud je to úspěšné, každé property_subpattern pole nebo vlastnost se přečte a jeho hodnota se shoduje s odpovídajícím vzorem. Výsledek celé shody je false pouze v případě, že výsledek některého z těchto výsledků je false. Pořadí, ve kterém se podpatterny shodují, není zadáno a neúspěšná shoda nemusí testovat všechny podpatterny za běhu. Pokud je shoda úspěšná a simple_designationproperty_pattern je single_variable_designation, deklarovaná proměnná se přiřadí odpovídající hodnotě.

Property_pattern lze použít k porovnávání vzorů s anonymními typy.

Subpattern_name může odkazovat na vnořený člen. V takovém případě je příjemce pro každé vyhledávání jmen typem předchozího člena T₀ počínaje vstupním typemproperty_pattern. Pokud je typ T s možnou hodnotou null, je T₀ jeho základním typem, jinak se T₀ rovná T. Například vzor formuláře { Prop1.Prop2: pattern } je přesně ekvivalentní { Prop1: { Prop2: pattern } }.

Poznámka: Tato možnost bude obsahovat kontrolu hodnoty null, pokud T je typ hodnoty null nebo odkazový typ. Tato kontrola null znamená, že dostupné vnořené vlastnosti budou vlastnosti T₀, ne T. Protože jsou povoleny opakované cesty členů, kompilace porovnávání vzorů může využívat běžné části vzorů. koncová poznámka

Příklad:

var o = ...;
if (o is string { Length: 5 } s) ...

konec příkladu

Příklad: Kontrola typu za běhu a deklarace proměnné lze přidat do vzoru vlastnosti následujícím způsobem:

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."),
};

Výstup je vytvořen.

Hello
Hi!
12345
abc

konec příkladu

11.2.7 Zahodit vzor

Každý výraz odpovídá vzoru zahození, což vede k zahození hodnoty výrazu.

discard_pattern
    : '_'
    ;

Jedná se o chybu v době kompilace použití vzoru zahození v relational_expressionrelational_expression formulářeisnebo jako vzor switch_label.

Poznámka: V těchto případech, aby se shodovaly s libovolným výrazem, použijte var_pattern s zahozením var _. koncová poznámka

Příklad:

Console.WriteLine(GetDiscountInPercent(DayOfWeek.Friday));
Console.WriteLine(GetDiscountInPercent(null));
Console.WriteLine(GetDiscountInPercent((DayOfWeek)10));

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,
};

Výstup je vytvořen.

5.0
0.0
0.0

Zde se vzor zahození používá ke zpracování null a jakékoli celočíselné hodnotě, která nemá odpovídající člen výčtu DayOfWeek . To zaručuje, že switch výraz zpracovává všechny možné vstupní hodnoty. konec příkladu

Vzor typu 11.2.8

Type_pattern slouží k otestování, že vstupní hodnota vzoru (§11.1) má daný typ.

type_pattern
    : type
    ;

Pojmenování T typu se vztahuje na každý typ E , pro který E je vzor kompatibilní s T (§11.2.2).

Typ modulu runtime hodnoty je testován proti typu pomocí stejných pravidel zadaných v operátoru is-type (§12.15.12.1). Pokud je test úspěšný, vzor odpovídá této hodnotě. Jedná se o chybu v době kompilace, pokud je typ typu s možnou hodnotou null. Tento vzorový formulář nikdy neodpovídá hodnotě null .

11.2.9 Relační vzor

Relational_pattern slouží k relačnímu testování vstupní hodnoty vzoru (§11.1) proti konstantní hodnotě.

relational_pattern
    : '<'  relational_expression
    | '<=' relational_expression
    | '>'  relational_expression
    | '>=' relational_expression
    ;

Relational_expression v relational_pattern se vyžaduje k vyhodnocení na konstantní hodnotu.

Relační vzorce podporují relační operátory <, <=, , >a >= na všech předdefinovaných typech, které podporují tyto binární relační operátory s oběma operandy se stejným typem: sbyte, byte, shortushort, , int, uint, longulongcharfloatdoubledecimalnintnuinta výčty.

Relational_pattern se vztahuje na typT, pokud je vhodný integrovaný binární relační operátor definován s oběma operandy typu T, nebo pokud explicitní převod nullable nebo unboxing existuje od T typu konstantního výrazu.

Jedná se o chybu v době kompilace, pokud se výraz vyhodnotí jako double.NaN, float.NaNnebo null konstanta.

Pokud má vstupní hodnota typ, pro který je definován vhodný předdefinovaný binární relační operátor, vyhodnocení tohoto operátoru se považuje za význam relačního vzoru. V opačném případě se vstupní hodnota převede na typ konstantního výrazu pomocí explicitního převodu s možnou hodnotou null nebo rozbalení. Jedná se o chybu v době kompilace, pokud neexistuje žádný takový převod. Model se považuje za nekohodný, pokud převod selže. Pokud převod proběhne úspěšně, výsledkem operace porovnávání vzorů je výsledek vyhodnocení výrazu e «op» v , kde e je převedený vstup, «op» je relační operátor a v je konstantní výraz.

Příklad:

Console.WriteLine(Classify(13));
Console.WriteLine(Classify(double.NaN));
Console.WriteLine(Classify(2.4));

static string Classify(double measurement) => measurement switch
{
    < -4.0 => "Too low",
    > 10.0 => "Too high",
    double.NaN => "Unknown",
    _ => "Acceptable",
};

Výstup je vytvořen.

Too high
Unknown
Acceptable

konec příkladu

11.2.10 Logický vzor

Logical_pattern slouží k negování výsledku shody vzorku nebo ke kombinování výsledků více shod vzorů pomocí spojení (and) nebo disjunkce (or).

logical_pattern
    : disjunctive_pattern
    ;

disjunctive_pattern
    : disjunctive_pattern 'or' conjunctive_pattern
    | conjunctive_pattern
    ;

conjunctive_pattern
    : conjunctive_pattern 'and' negated_pattern
    | negated_pattern
    ;

negated_pattern
    : 'not' negated_pattern
    | primary_pattern
    ;

not, anda or jsou souhrnně označovány jako operátory vzorů.

Negated_pattern odpovídá, pokud se vzor negovaný neshoduje a naopak. Conjunctive_pattern vyžaduje, aby se oba vzory shodovaly. Disjunctive_pattern vyžaduje, aby se shodovaly oba vzory. Na rozdíl od jejich jazykových operátorů a a &&|| operátory andor zkratování.

Jedná se o chybu v době kompilace pro deklarování proměnné vzoru pod operátorem nebo not operátorem or vzoru.

Poznámka: Protože ani nemůže notor vytvořit určité přiřazení pro proměnnou vzoru, jedná se o chybu deklarování jedné z těchto pozic. koncová poznámka

V conjunctive_pattern je vstupní typ druhého vzoru zúžen požadavky na zúžení typu prvního vzoru and. Zúžený typ vzoru P je definován takto:

  • Pokud P je vzor typu, zúžený typ je typ vzoru typu.
  • V opačném případě, pokud P je vzor deklarace, zúžený typ je typ modelu deklarace.
  • V opačném případě, pokud P je rekurzivní vzor, který dává explicitní typ, zúžený typ je tento typ.
  • V opačném případě je-li P shodován pomocí pravidel pro ITuplepositional_pattern (§11.2.5), je zúžený typ typu System.ITuple.
  • Jinak je-li P konstantní vzor, kde konstanta není nulová konstanta a kde výraz nemá žádný konstantní převod výrazu na vstupní typ, zúžený typ je typ konstanty.
  • V opačném případě je-li P relační vzor, kde konstantní výraz nemá žádný konstantní výraz převod na vstupní typ, zúžený typ je typ konstanty.
  • V opačném případě, pokud P je or vzor, je zúžený typzúžený typ podpatternů, pokud takový společný typ existuje. Pro tento účel algoritmus běžného typu bere v úvahu pouze převody identity, boxingu a implicitního odkazu a bere v úvahu všechny podpatterny posloupnosti or vzorů (ignoruje závorky).
  • V opačném případě, pokud P je and vzor, zúžený typ je zúžený typ správného vzoru. Zúžený typ levého vzorku je navíc vstupním typem pravého vzoru.
  • V opačném případě je zúžený typ vstupního PPtypu.

Poznámka: Jak je uvedeno gramatikou, not má přednost před and, který má přednost před or. To může být explicitně označeno nebo přepsáno pomocí závorek. koncová poznámka

Když se vzor objeví na pravé straně is, rozsah vzoru je určen gramatikou; v důsledku toho operátory andvzoru , ora not v rámci vzoru svázat těsněji než logické operátory &&, ||a ! mimo vzor.

Příklad:

Console.WriteLine(Classify(13));
Console.WriteLine(Classify(-100));
Console.WriteLine(Classify(5.7));

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",
};

Výstup je vytvořen.

High
Too low
Acceptable

konec příkladu

Příklad:

Console.WriteLine(GetCalendarSeason(new DateTime(2021, 1, 19)));
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 10, 9)));
Console.WriteLine(GetCalendarSeason(new DateTime(2021, 5, 11)));

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}."),
};

Výstup je vytvořen.

winter
autumn
spring

konec příkladu

Příklad:

object msg = "msg";
object obj = 5;
bool flag = true;

// This is parsed as: (msg is (not int) or string)
result = msg is not int or string;
Console.WriteLine($"msg (\"msg\"): msg is not int or string: {result}");

// This is parsed as: (obj is (int or string)) && flag
bool result = obj is int or string && flag;
Console.WriteLine($"obj (5), flag (true): obj is int or string && flag: {result}");

// This is parsed as: (obj is int) || ((obj is string) && flag)
result = obj is int || obj is string && flag;
Console.WriteLine($"obj (5), flag (true): obj is int || obj is string && flag: {result}");

flag = false;
// This is parsed as: (obj is (int or string)) && flag
result = obj is int or string && flag;
Console.WriteLine($"obj (5), flag (false): obj is int or string && flag: {result}");

// This is parsed as: (obj is int) || ((obj is string) && flag)
result = obj is int || obj is string && flag;
Console.WriteLine($"obj (5), flag (false): obj is int || obj is string && flag: {result}");

Výstup je vytvořen.

msg ("msg"): msg is not int or string: True
obj (5), flag (true): obj is int or string && flag: True
obj (5), flag (true): obj is int || obj is string && flag: True
obj (5), flag (false): obj is int or string && flag: False
obj (5), flag (false): obj is int || obj is string && flag: True

konec příkladu

11.3 Dílčí podsumpce vzorku

V příkazu switch se jedná o chybu, pokud je vzor případu podsoučet předchozí sadou nehlídaných případů (§13.8.3). Neformálně to znamená, že jakákoli vstupní hodnota by se shodovala s jednou z předchozích případů. Následující pravidla definují, kdy sada vzorů podsoustaví daný vzor:

Vzor Pby se shodoval s konstantou K v případě, že se uchovávají některé z následujících podmínek:

  • specifikace chování modulu runtime daného vzoru odpovídá PK.
  • P je type_pattern pro typ T a K není null a typ modulu runtime K je T nebo typ odvozený z T nebo typ, který implementuje T.
  • P je relational_pattern s operátorem «op» a konstantou v, a výraz K «op» v by byl vyhodnocen jako true.
  • P je negated_patternnot P₁ a P₁ neodpovídá K.
  • P je conjunctive_patternP₁ and P₂ a oba P₁ by odpovídaly K a P₂ odpovídaly K.
  • P je disjunctive_patternP₁ or P₂ a buď P₁ by se shodoval K , nebo P₂ by odpovídal K.
  • P je discard_pattern.

Sada vzorů Qpodsoustaví vzor P , pokud se drží některé z následujících podmínek:

  • Pje konstantní vzor a libovolný ze vzorů v sadě Q by odpovídal Ppřevedené hodnotě.
  • Pje vzor var a sada vzorů je vyčerpávající (§11.4) pro typ vstupní hodnoty vzoru (Q) a buď vstupní hodnota vzoru není typu null, nebo by se shodoval nějaký vzor.Qnull
  • P je vzor deklarace s typem T a sada vzorů Q je vyčerpávající pro typ T (§11.4).
  • P je type_pattern pro typ T a sada vzorů Q je pro typ Tvyčerpávající .
  • P je relational_pattern s operátorem «op» a konstantní hodnotou v, a pro každou hodnotu vstupního typu vyhovující relační «op» v, určitý vzor v sadě Q by odpovídal této hodnotě.
  • P je disjunctive_patternP₁ or P₂ a sada dílčích vzorů QP₁ a Q dílčích motivů P₂.
  • P je conjunctive_patternP₁ and P₂ a alespoň jeden z následujících blokování: Q subsumes P₁, nebo Q subsumes P₂.
  • P je negated_patternnot P₁ a Q je vyčerpávající pro vstupní typ s ohledem pouze na hodnoty, které P₁neodpovídají .
  • P je discard_pattern a sada vzorů Q je vyčerpávající pro typ vstupní hodnoty vzoru, a buď vstupní hodnota vzoru není typu s možnou hodnotou null, nebo nějaký vzor by Q odpovídal null.
  • Nějaký vzor Q je disjunctive_patternQ₁ or Q₂ a nahrazením daného vzoru Q₁Q by přineslo sadu, která se podsoučty P, nebo nahrazení Q₂ by přinesla sadu, která se podsoubí P.
  • Určitý vzor Q je negated_patternnot Q₁ a P neodpovídá žádné hodnotě, která Q₁ by se shodovala.

11.4 Úplnost vzoru

Neformálně je sada vzorů pro typ vyčerpávající, pokud platí pro každou možnou hodnotu tohoto typu kromě hodnoty null, je možné použít nějaký vzor v sadě. Následující pravidla definují, kdy je sada vzorů pro typ vyčerpávající :

Sada vzorů Q je , pokud jsou splněny některé z následujících podmínek:

  1. T je celočíselný nebo výčtový typ nebo verze jednoho z nich s možnou hodnotou null a pro každou možnou hodnotu základního Ttypu, která Q není nullable, by se určitý vzor shodoval s danou hodnotou;
  2. Určitý vzor v Q je var vzor; nebo
  3. Určitý vzor je Qvzor deklarace pro typ Da existuje převod identity, implicitní převod odkazu nebo boxing převodu z TD; nebo
  4. Určitý vzor Q je type_pattern pro typ Da existuje převod identity, implicitní převod odkazu nebo boxing převod z TD; nebo
  5. Určitý vzor je Qdiscard_pattern; nebo
  6. Vzory Q zahrnují kombinaci relational_patterns a constant_patterns, jejichž rozsahy souhrnně pokrývají všechny možné hodnoty základního Ttypu bez hodnoty null. U float a double typech to zahrnuje System.Double.NaN nebo System.Single.NaN v uvedeném pořadí, protože NaN se neshoduje s žádným relačním vzorem; nebo
  7. Určitý vzor Q je disjunctive_patternP₁ or P₂ a nahrazením daného vzoru P₁ oběma a P₂ vynese Q sadu, která je vyčerpávající pro T; nebo
  8. Určitý vzor v Q je negated_patternnot P₁ a vzory společně Q s hodnotami, které nejsou spárovány P₁ pokrytím všech možných hodnot T. Negated_patternnot P₁ je sám o sobě vyčerpávající, pokud P₁ neodpovídá žádné možné hodnotě T; nebo
  9. V některých vzorech Q je conjunctive_patternP₁ and P₂ a sada obsahující pouze P₁je vyčerpávajícíT a sada obsahující pouze P₂je vyčerpávající pro T.

Poznámka: Pokud vzor typu obsahuje typy s možnou hodnotou null, může být vzor pro typ vyčerpávající, ale přesto vygeneruje upozornění, protože vzor typu neodpovídá hodnotě null . koncová poznámka

Poznámka: U typů s plovoucí desetinou čárkou není kombinace vzorů < 0 a >= 0není vyčerpávající, protože relační vzor neodpovídá NaN. Správná vyčerpávající sada by byla < 0, >= 0a double.NaN (nebo float.NaN). koncová poznámka

Příklad:

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;
    }
}

konec příkladu