11 Minták és minták egyeztetése

11.1 Általános

A minta egy szintaktikai forma, amely az operátorral is (12.15.12.§), egy switch_statement (13.8.3. §) és egy switch_expression (12.12. §) használható azon adatok alakjának kifejezésére, amelyekhez a bejövő adatokat össze kell hasonlítani. A minták rekurzívak lehetnek, így az adatok egy része megfeleltethető az almintáknak.

A minta több környezetben is tesztelve van egy értéken:

  • Egy kapcsolóutasításban a rendszer a kis- és nagybetűk címkéjének mintáját teszteli a kapcsolóutasítás kifejezésével .
  • Az is-pattern operátorban a jobb oldali minta a bal oldali kifejezésen van tesztelve.
  • Egy kapcsolókifejezésben a switch_expression_armmintáját a kapcsolókifejezés bal oldalán lévő kifejezéssel teszteljük.
  • Beágyazott környezetekben az alminta a tulajdonságokból, mezőkből vagy más bemeneti értékekből indexelt értékeken van tesztelve a minta űrlapjától függően.

Azt az értéket, amely alapján a minta tesztelése történik, a minta bemeneti értékének nevezzük.

11.2 Mintaalakok

11.2.1 Általános

Egy minta a következő űrlapok egyikével rendelkezhet:

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

Az '(' pattern ')' éles környezet lehetővé teszi, hogy zárójelek közé zárjon egy mintát, hogy kényszerítse a minták közötti kiértékelési sorrendet a logical_patternegyikével kombinálva.

Egyes mintákhelyi változó deklarációját eredményezhetik.

Minden mintaűrlap meghatározza a minta által alkalmazható bemeneti értékek típusait. A minta P akkor , ha T azon típusok közé tartozik, amelyek értékei megegyezhetnek a mintával. Fordítási idejű hiba, ha egy minta P egy olyan programban jelenik meg, amely megfelel egy minta bemeneti értékének (T. §), ha P az nem alkalmazható.T

Példa: Az alábbi példa fordítási időt eredményez, mert a fordítási idő típusa v .TextReader Egy típusú TextReader változó soha nem rendelkezhet olyan értékkel, amely hivatkozással stringkompatibilis:

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

Az alábbiak azonban nem okoznak fordítási időt, mert a fordítási idő típusa v .object Egy típusváltozó object olyan értékkel rendelkezhet, amely hivatkozással kompatibilis a következőkkel string:

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

záró példa

Minden mintaűrlap meghatározza azokat az értékeket, amelyek esetében a minta futásidőben megegyezik az értékkel.

Nincs megadva a műveletek és a mellékhatások kiértékelésének sorrendje a mintaegyeztetés során (a hívások Deconstruct, a tulajdonsághozzáférések és a metódusok System.ITuplemeghívása).

11.2.2 Deklarációs minta

A declaration_pattern annak tesztelésére szolgál, hogy egy értéknek van-e egy adott típusa, és ha a teszt sikeres, az adott típusú változó értékének megadása opcionálisan.

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

A jogkivonattal rendelkező _single_variable_designation helyett discard_designation kell tekinteni.

Az érték futtatókörnyezeti típusát a rendszer a mintában szereplő típussal teszteli az is-type operátorban megadott szabályokkal (12.15.12.1. §). Ha a teszt sikeres, a minta megfelel ennek az értéknek. Fordítási idejű hiba, ha a típus null értékű (8.3.12. §) vagy null értékű hivatkozástípus (8.9.3. §). Ez a mintaűrlap soha nem egyezik meg egy null értékkel.

Megjegyzés: Az is-type kifejezés e is T és a deklarációs minta e is T _ egyenértékű, ha T nem null értékű típus. végjegyzet

Ha a minta bemeneti értéke (11.1.§) e, ha a simple_designationdiscard_designation, akkor a visszavetést jelöli (9.2.9.2. §), és az e érték nem kötődik semmihez. (Bár a névvel _ rendelkező deklarált változók hatókörben lehetnek, az elnevezett változó ebben a kontextusban nem jelenik meg.) Ellenkező esetben, ha a simple_designationsingle_variable_designation, a rendszer bevezet egy helyi változót (9.2.9. §) az adott azonosító által elnevezett adott típusból. Ez a helyi változó a minta bemeneti értékének értékét rendeli hozzá, ha a minta megfelel az értéknek.

A minta bemeneti értékének és az adott típus statikus típusának bizonyos kombinációi nem kompatibilisek, és fordítási időt eredményeznek. A statikus típusú E értékeknek a típussal kell lenniük, ha létezik identitáskonverzió, implicit vagy explicit referenciaátalakítás, dobozos átalakítás, nem dobozos átalakítás, vagy implicit vagy explicit null értékű érték típusú átalakítás, amelyről a típusra TE vált, vagy nyitott TE típus (T). A típus T amely E a mintával Ekompatibilis.

Megjegyzés: A nyitott típusok támogatása leginkább akkor lehet hasznos, ha olyan típusokat ellenőriz, amelyek lehetnek strukturált vagy osztálytípusok, és kerülni kell a boxolást. végjegyzet

Példa: A deklarálási minta hasznos a referenciatípusok futásidejű típustesztjeihez, és lecseréli az idiómát

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

a kissé tömörebb

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

záró példa

Példa: A deklarálási minta használható null értékű értékek tesztelésére: egy típus ( Nullable<T> vagy egy dobozos T) érték megfelel egy típusmintának T2 id , ha az érték nem null értékű, és T2 az T, vagy a típus valamilyen alaptípusa Tvagy felülete. Például a kódtöredékben

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

Az utasítás állapota if futásidőben vantrue, és a változó v a blokkon belül tárolja a típus 3 értékétint. A blokk után a változó v hatókörben van, de nem feltétlenül van hozzárendelve. záró példa

11.2.3 Állandó minta

Egy constant_pattern egy minta bemeneti értékének (11.1. §) az adott állandó értéken való tesztelésére szolgál.

constant_pattern
    : constant_expression
    ;

Az állandó minta P akkor , ha implicit átalakítás történik az állandó kifejezésből T a típusba P.

Állandó minta Pesetén a konvertált érték a következő:

  • ha a minta bemeneti értékének típusa integráltípus vagy számtípus, akkor a minta állandó értéke erre a típusra lesz konvertálva; egyébként
  • ha a minta bemeneti értéke egy integrál- vagy számtípus null értékű verziója, a minta állandó értéke az alapul szolgáló típussá alakul át; egyébként
  • a minta állandó értékének értéke.

Az e mintául szolgáló bemeneti érték és a konvertált v értékkel rendelkező állandó mintaP,

  • ha e integráltípussal vagy számtípussal rendelkezik, vagy az egyiknek null értékű formája van, és v integráltípussal rendelkezik, a minta P megfelel az e értéknek, ha a kifejezés e == vtrueeredménye; egyébként
  • a minta Pmegfelel az e értéknek, ha object.Equals(e, v) visszaadjatrue.

Példa: A switch következő metódusban szereplő utasítás öt állandó mintát használ a kis- és nagybetűk címkéiben.

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

záró példa

11.2.4 Var minta

Egy var_patternminden értéknek megfelel . Ez azt jelzi, hogy egy mintaegyeztetés mindig sikeres var_pattern.

A var_patternminden típusra alkalmazható.

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

A minta bemeneti értéke (11.1.§) e, ha a megjelölésdiscard_designation, akkor elvetésnek (9.2.9.2. §) jelöli, és az e érték semmihez nem kötődik. (Bár az ilyen nevű deklarált változók a hatókörben lehetnek, az elnevezett változó ebben a kontextusban nem látható.) Ellenkező esetben, ha a megjelöléssingle_variable_designation, futásidőben az e érték egy újonnan bevezetett helyi változóhoz (9.2.9. §) van kötve, amelynek típusa az e statikus típus, és a minta bemeneti értéke hozzá van rendelve ehhez a helyi változóhoz.

Hiba, ha a név var olyan típushoz kötődik, amelyben egy var_pattern használ.

Ha a megjelöléstuple_designation, a minta egyenértékű az űrlap megjelölésének(var (11.2.5.§), ... ) ahol a megjelölésaz tuple_designation belül található. A minta var (x, (y, z)) például egyenértékű a következő értékével (var x, (var y, var z)): .

11.2.5 Pozícióminta

A positional_pattern ellenőrzi, hogy a bemeneti érték nem null, meghív egy megfelelő Deconstruct metódust (12.7. §), és további mintaegyezést végez az eredményként kapott értékeken. Emellett támogatja a rekordszerű mintaszintaxist (a típus megadása nélkül), ha a bemeneti érték típusa megegyezik az azt tartalmazó Deconstructtípussal, vagy ha a bemeneti érték típusa tuple típusú, vagy ha a bemeneti érték object típusa vagy System.ITuple a kifejezés futtatókörnyezeti típusa implementálódik System.ITuple.

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

Mivel a bemeneti érték megegyezik a minta típusú(alpatterekéval), a rendszer úgy választ ki egy metódust, hogy típust keres az akadálymentes deklarációkhoz Deconstruct , és kiválaszt egyet közülük ugyanazokkal a szabályokkal, mint a dekonstruálási deklaráció esetében. Hiba, ha egy positional_pattern kihagyja a típust, egyetlen alhálózata van azonosító nélkül, nincs property_subpattern és nincs simple_designation. Ez nem egyértelmű a zárójeles constant_pattern és a positional_pattern között. A lista mintáival egyező értékek kinyeréséhez

  • Ha a típus nincs megadva, és a bemeneti kifejezés típusa tuple típusú, akkor az alutasítók számának meg kell egyeznie a rekord számosságával. Minden elemet egyeztet a megfelelő alhálózattal, és az egyezés sikeres lesz, ha ezek mindegyike sikeres. Ha bármely alpattern rendelkezik azonosítóval, akkor az a típus megfelelő helyén egy lécelemet nevez el.
  • Ellenkező esetben, ha egy megfelelő Deconstruct típus tagjaként létezik, fordítási idő hibát jelent, ha a bemeneti érték típusa nem kompatibilis a típussal. Futásidőben a bemeneti érték típuson van tesztelve. Ha ez nem sikerül, akkor a pozícióminta egyezése meghiúsul. Ha sikeres, a bemeneti érték ilyen típusra lesz konvertálva, és Deconstruct a rendszer új fordító által létrehozott változókkal hívja meg a kimeneti paraméterek fogadásához. Minden fogadott érték megfelel a megfelelő alhálózatnak, és a találat sikeres lesz, ha ezek mindegyike sikeres. Ha bármely alpattern rendelkezik azonosítóval, akkor a paraméternek a megfelelő pozícióban kell megadnia a paramétert Deconstruct.
  • Ellenkező esetben, ha a típus nincs megadva, és a bemeneti érték típus object vagy valamilyen olyan típus, amely implicit hivatkozáskonvertálással konvertálható System.ITuple , és az alutasítók között nem jelenik meg azonosító , akkor az egyezést használja System.ITuple.
  • Ellenkező esetben a minta fordítási idejű hiba.

Az alhálózatok futásidőben való egyeztetésének sorrendje nem meghatározott, és előfordulhat, hogy egy sikertelen egyezés nem próbálja meg az összes alhálózatot egyeztetni.

Példa: Itt egy kifejezés eredményét bontjuk fel, és az eredményként kapott értékeket a megfelelő beágyazott mintákkal egyeztetjük:

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

záró példa

Példa: A rekordelemek és a Deconstruct paraméterek neve a következőképpen használható egy pozíciómintában:

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

A létrehozott kimenet a következő:

Sum of [10 20 30] is 60

záró példa

11.2.6 Tulajdonságminta

A property_pattern ellenőrzi, hogy a bemeneti érték nem null, és rekurzívan egyezik-e az akadálymentes tulajdonságok vagy mezők használatával kinyert értékekkel.

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

Hiba, ha egy property_pattern egyik alpatterje sem tartalmaz subpattern_name.

Fordítási idejű hiba, ha a típus null értékű (8.3.12. §) vagy null értékű hivatkozástípus (8.9.3. §).

Megjegyzés: A null-ellenőrző minta kiesik egy triviális tulajdonságmintából. Ha ellenőrizni szeretné, hogy a sztring s nem null értékű-e, az alábbi űrlapok bármelyikét megírhatja:

#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 {}) ...

végjegyzet

Az e kifejezésnek a mintatípus{alpattereivel} való egyezése miatt fordítási idő hibát jelent, ha az e kifejezés nem felel meg a típus szerint kijelölt T típusnak. Ha a típus hiányzik, a rendszer feltételezi, hogy a típus az e statikus típusa. Minden subpattern_name, amely az alhálózatok bal oldalán jelenik meg, a T elérhető olvasható tulajdonságát vagy mezőjét kell kijelölnie. Ha a property_pattern simple_designation jelen van, egy T típusú mintaváltozót deklarál.

Futásidőben a kifejezés tesztelése T-n történik. Ha ez nem sikerül, akkor a tulajdonságminta egyezik, és az eredmény a következő false. Ha sikerül, akkor minden property_subpattern mező vagy tulajdonság beolvasva, és az értéke megfelel a megfelelő mintának. A teljes egyezés eredménye csak akkor vanfalse, ha ezek bármelyikének eredménye .false Az alhálózatok egyeztetési sorrendje nincs megadva, és előfordulhat, hogy egy sikertelen egyezés nem teszteli az összes alhálózatot futásidőben. Ha az egyezés sikeres, és a property_pattern simple_designationegy single_variable_designation, a deklarált változó hozzárendeli a megfeleltetett értéket.

A property_pattern a névtelen típusokkal való mintaegyezésre használható.

A subpattern_name hivatkozhatnak beágyazott tagra. Ilyen esetben az egyes névkeresések fogadója az előző tag T₀ típusa, a property_patternbemeneti típusától kezdve. Ha A T null értékű típus, akkor a T₀ a mögöttes típus, ellenkező esetben a T₀ értéke T. Az űrlap { Prop1.Prop2: pattern } mintázata például pontosan egyenértékű a következővel { Prop1: { Prop2: pattern } }:

Megjegyzés: Ez magában foglalja a null ellenőrzést, ha a T null értékű vagy hivatkozástípus. Ez a null-ellenőrzés azt jelenti, hogy az elérhető beágyazott tulajdonságok a T₀ tulajdonságai lesznek, nem pedig a T tulajdonsága. Mivel az ismétlődő tagútvonalak engedélyezettek, a mintaegyezés összeállítása kihasználhatja a minták gyakori részeit. végjegyzet

Példa:

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

záró példa

Példa: Egy futásidejű típusellenőrzés és egy változódeklaráció hozzáadható egy tulajdonságmintához az alábbiak szerint:

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

A létrehozott kimenet a következő:

Hello
Hi!
12345
abc

záró példa

11.2.7 Elvetési minta

Minden kifejezés megegyezik az elvetési mintával, ami a kifejezés elvetésének értékét eredményezi.

discard_pattern
    : '_'
    ;

Fordítási idő hiba az űrlapis relational_expressionmintájában vagy egy switch_label mintájaként használt elvetési minta használata.

Megjegyzés: Ezekben az esetekben a kifejezések egyeztetéséhez használjon var_pattern elvetéssel var _. végjegyzet

Példa:

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

A létrehozott kimenet a következő:

5.0
0.0
0.0

Itt egy elvetési mintát használunk a kezeléshez null , és minden olyan egész számértéket, amely nem rendelkezik az DayOfWeek enumerálás megfelelő tagjával. Ez garantálja, hogy a switch kifejezés minden lehetséges bemeneti értéket kezel. záró példa

11.2.8 Típusminta

Egy type_pattern annak ellenőrzésére szolgál, hogy a minta bemeneti értéke (11.1. §) egy adott típussal rendelkezik-e.

type_pattern
    : type
    ;

A típus T elnevezésére szolgáló típusminta minden olyan típusraE alkalmazható, amelynek EmintájaT kompatibilis (11.2.2.2. §).

Az érték futtatókörnyezettípusát az is-type operátorban megadott szabályokkal teszteli a rendszer (12.15.12.1. §). Ha a teszt sikeres, a minta megfelel ennek az értéknek. Fordítási idejű hiba, ha a típus null értékű. Ez a mintaűrlap soha nem egyezik meg egy null értékkel.

11.2.9 Relációs minta

A relational_pattern a minta bemeneti értékének (11.1.§) relációs tesztelésére szolgál egy állandó értéken.

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

A relational_pattern relational_expression állandó értékre kell kiértékelni.

A relációs minták támogatják a relációs operátorokat , , , és < az összes olyan beépített típust, amely támogatja az ilyen bináris relációs operátorokat, és mindkét operandus azonos típusú: <=, >, >=, sbyte, byteshortushortintuintlongulongcharfloatdoubleés számokat. decimalnintnuint

A relational_pattern akkor alkalmazható egy típusraT, ha a megfelelő beépített bináris relációs operátor mindkét típusú Toperandussal van definiálva, vagy ha a konstans kifejezés típusához T explicit null értékű vagy nem dobozoló átalakítás tartozik.

Fordítási idő hiba, ha a kifejezés kiértékelése double.NaN: , float.NaNvagy null állandó.

Ha a bemeneti érték olyan típussal rendelkezik, amelyhez egy megfelelő beépített bináris relációs operátor van meghatározva, az operátor kiértékelése a relációs minta jelentése. Ellenkező esetben a bemeneti érték az állandó kifejezés típusává lesz konvertálva explicit null értékű vagy nemboxolásos átalakítással. Fordítási idejű hiba, ha nincs ilyen átalakítás. A minta nem egyezik, ha az átalakítás sikertelen. Ha az átalakítás sikeres, a mintaegyeztetési művelet eredménye a konvertált bemenetet tartalmazó e «op» v kifejezés e kiértékelésének eredménye, az "op" a relációs operátor, és v az állandó kifejezés.

Példa:

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

A létrehozott kimenet a következő:

Too high
Unknown
Acceptable

záró példa

11.2.10 Logikai minta

A logical_pattern egy mintaegyezés eredményének tagadására, vagy több mintaegyezés eredményének egyesítésére szolgál kötőszó (and) vagy tiltás (or) használatával.

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, andés or együttesen mintaoperátoroknak nevezzük őket.

A negated_pattern akkor egyeznek, ha a negated minta nem egyezik, és fordítva. A conjunctive_pattern mindkét mintának meg kell egyeznie. A disjunctive_pattern mindkét mintát meg kell egyeznie. Ellentétben a nyelvi operátor megfelelőivel, &&|| és andornem rövidzárlatú operátorok.

Fordítási idő hiba, ha egy mintaváltozót egy vagy not minta or operátor alatt deklarálnak.

Megjegyzés: Mivel a mintaváltozókhoz nem notor lehet határozott hozzárendelést létrehozni, hiba az ilyen pozíciók egyikének deklarálása. végjegyzet

Egy conjunctive_pattern a második minta bemeneti típusát az első minta típusszűkítési követelményei szűkítik and. A minta P a következőképpen van definiálva:

  • Ha P típusminta, akkor a szűkített típus a típusminta típusának típusa.
  • Ellenkező esetben, ha P deklarációs minta, a szűkített típus a deklarációs minta típusának típusa.
  • Ellenkező esetben, ha P egy rekurzív minta explicit típust ad, akkor a leszűkített típus az a típus.
  • Ellenkező esetben, ha P egy positional_pattern szabályai ITuple (11.2.5. §) alapján egyeznek meg, a szűkített típus a típusSystem.ITuple.
  • Ellenkező esetben, ha P állandó minta, ahol az állandó nem null állandó, és ahol a kifejezés nem rendelkezik állandó kifejezéskonvertálással a bemeneti típusra, akkor a leszűkített típus az állandó típusa.
  • Ellenkező esetben, ha P olyan relációs minta, amelyben az állandó kifejezés nem rendelkezik állandó kifejezéskonvertálással a bemeneti típusra, a szűkített típus az állandó típusa.
  • Ellenkező esetben, ha P minta or , akkor a keskenyített típus az alhálózatok szűkített típusának közös típusa , ha létezik ilyen közös típus. Ebből a célból a közös típusú algoritmus csak identitás-, boxing- és implicit referenciakonverziókat vesz figyelembe, és figyelembe veszi a minták sorozatának or összes alpatterét (figyelmen kívül hagyva a zárójeles mintákat).
  • Ellenkező esetben, ha P minta and , akkor a szűkített típus a megfelelő minta szűkített típusa . Ezenkívül a bal minta szűkített típusa a jobb minta bemeneti típusa .
  • Ellenkező esetben a leszűkített típusP a Pbemeneti típus.

Megjegyzés: Ahogy a nyelvtan is jelzi, not elsőbbséget élvez a következővel szembenandor: Ez zárójelek használatával explicit módon jelezhető vagy felülírható. végjegyzet

Ha a minta a jobb oldalon isjelenik meg, a minta mértékét a nyelvtan határozza meg; ennek eredményeképpen a minta operátorai andor, és not a mintán belül szorosabban kötődnek, mint a logikai operátorok &&, ||és ! a mintán kívül.

Példa:

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

A létrehozott kimenet a következő:

High
Too low
Acceptable

záró példa

Példa:

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

A létrehozott kimenet a következő:

winter
autumn
spring

záró példa

Példa:

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

A létrehozott kimenet a következő:

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

záró példa

11.3 Minta-részsumpció

A kapcsolóutasításban hiba, ha egy eset mintáját az előző, nem őrzött esetek halmaza (13.8.3. §) aláveti. Informálisan ez azt jelenti, hogy minden bemeneti érték megfelelt volna az előző esetek egyikének. A következő szabályok határozzák meg, hogy egy mintakészlet mikor ad részösszeget egy adott mintának:

Egy minta Pakkor egyezik meg egy állandóval K , ha az alábbi feltételek bármelyike fennáll:

  • A minta futtatókörnyezeti viselkedésének specifikációja megegyezik PK.
  • P egy type_pattern a típushoz T , és K nem null , és a futtatókörnyezet típusa K származik TT vagy egy implementált Ttípus.
  • Pegy relational_pattern az "op" operátorral és az állandóvalv, és az "op" K kifejezés v kiértékelése a következő lesztrue: .
  • P egy negated_patternnot P₁ , és P₁ nem egyezik K.
  • P egy conjunctive_patternP₁ and P₂ , és mindkettő P₁ egyezik K , és P₂ megfelelne K.
  • P egy disjunctive_patternP₁ or P₂ , és vagy P₁ egyezik K vagy P₂ egyezik K.
  • Pdiscard_pattern.

A minták Qegy halmaza alávet egy mintát P , ha az alábbi feltételek bármelyike fennáll:

  • P állandó minta, és a készlet Q bármely mintája megegyezik Pa konvertált értékével
  • P egy var minta, és a minták Qkészlete teljes (11.4. §) a minta bemeneti értékének típusához (11.1. §), és vagy a minta bemeneti értéke nem null értékű, vagy egy minta Q egyezik null.
  • P egy típussal T rendelkező deklarációs Qminta, és a minták készlete teljes a típusra T vonatkozóan (11.4. §).
  • P type_pattern a típushoz T , és a minták Q teljes halmaza a típushozTtartozik.
  • P egy relational_pattern az "op" operátorral és az állandó értékkel v, és a bemeneti típus minden olyan értékéhez, amely megfelel az "op" vrelációnak, a készlet Q egy bizonyos mintája megfelelne ennek az értéknek.
  • P a disjunctive_patternP₁ or P₂ és a minták Q alösszegeinek P₁ és Q alösszegeinek halmaza P₂.
  • P egy conjunctive_patternP₁ and P₂ , és legalább az alábbiak egyikét tartalmazza: Q alösszegek P₁vagy Q alösszegek P₂.
  • P egy negated_patternnot P₁ , és Q a bemeneti típus teljes körű , figyelembe véve csak azokat az értékeket, amelyeket P₁nem egyeznek meg.
  • P egy discard_pattern , és a minták Q készlete teljes a minta bemeneti értékének típusára vonatkozóan, és vagy a minta bemeneti értéke nem null értékű, vagy egy minta Q egyezik null.
  • Néhány minta Q egy disjunctive_patternQ₁ or Q₂ , és ha ezt a mintát in értékre Q₁Q cserélné , az olyan készletet eredményezne, amely alösszegeket Peredményezne , vagy ha lecserélné azt Q₂ , akkor ez az alösszegek Phalmazt eredményezne .
  • Egyes minták Qnegated_patternnot Q₁ , és P nem egyeznek meg egyetlen értékkel Q₁ sem.

11.4 Minta teljessége

Informálisan a minták egy típusra vonatkozóan teljes körűek, ha a nulltól eltérő típus minden lehetséges értékére alkalmazható valamilyen minta a készletben. Az alábbi szabályok határozzák meg, hogy egy típus esetében egy mintakészlet mikor teljes:

Egy típusra Q vonatkozó minták teljes körűek, ha az alábbi feltételek bármelyike fennáll:

  1. T egy integrál- vagy számtípus, vagy ezek egyikének null értékű verziója, és a "nem null értékű mögöttes típus" minden lehetséges értékéhez Tbizonyos minta Q megfelelne ennek az értéknek; vagy
  2. Néhány minta Q egy var minta; vagy
  3. A minta Q egy típus D, és van egy identitáskonverzió, egy implicit referenciakonvertálás, vagy egy dobozos átalakítás a típusról TD; vagy
  4. A minta Q egy type_pattern típushoz D, és van egy identitáskonverzió, egy implicit referenciakonvertálás, vagy egy keretkonvertálás a típusról TDaz ; vagy
  5. Néhány minta Q egy discard_pattern; vagy
  6. A minták olyan Qrelational_patternés constant_patterns kombinációját tartalmazzák, amelyek tartományai együttesen lefedik a "nem null értékű mögöttes típus" összes lehetséges értékét T. float A double relációs mintával nem egyezik meg; vagy System.Double.NaN nem felel meg a relációs System.Single.NaN mintának, NaN vagy
  7. Néhány minta Q egy disjunctive_patternP₁ or P₂, és felváltja ezt a mintát mind P₁ a P₂Q hozamok egy készlet, amely kimerítőT; vagy
  8. Néhány minta Q egy negated_patternnot P₁, és a minták Q a nem egyező P₁ értékekkel együtt lefedik a lehetséges értékeket T. A negated_patternnot P₁ önmagában teljes körű, ha P₁ nem felel meg az T; vagy
  9. Néhány minta Qegy conjunctive_patternP₁ and P₂, és a csak P₁ a teljesT értéket tartalmazó készlet teljes, és a csak P₂ a teljes halmazt Ttartalmazza.

Megjegyzés: Ha egy típusminta null értékű típusokat tartalmaz, előfordulhat, hogy a minta teljes a típusra vonatkozóan, de figyelmeztetést is generál, mert a típusminta nem egyezik meg egy null értékkel. végjegyzet

Megjegyzés: A lebegőpontos típusok esetében a minták < 0>= 0 kombinációja nem teljes, mert egyik relációs minta sem egyezik NaN. A teljesség igénye a következő lenne < 0: , >= 0és double.NaN (vagy float.NaN). végjegyzet

Példa:

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

záró példa