Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
11.1 Általános
Az operátorral is (12.15.12.§), egy switch_statement (13.8.3. §) és egy switch_expression (12.12. §) mintával lehet leírni azokat az adatokat, amelyekhez a bejövő adatokat össze kell hasonlítani. A minták beágyazhatók, és az adatok egyes részei almintákkal egyeznek.
A minta több környezetben is tesztelve van egy értéken:
- Egy switch_statement egy switch_labelmintáját a switch_statement selector_expression teszteli.
- Az is-pattern operátorral a jobb oldalon lévő minta a bal oldali kifejezésen lesz tesztelve.
- Egy switch_expression egy switch_expression_armmintáját teszteli a switch_expression bal oldalán lévő kifejezéssel.
- 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
| logical_pattern
| list_pattern
| slice_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.
Ha a bemenet szintaktikailag felismerhető constant_pattern és positional_pattern is, akkor a constant_pattern kell kiválasztani.
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.TextReaderEgy típusúTextReaderváltozó soha nem rendelkezhet olyan értékkel, amely hivatkozássalstringkompatibilis: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.objectEgy típusváltozóobjectolyan értékkel rendelkezhet, amely hivatkozással kompatibilis a következőkkelstring: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ési sorrendje a mintaegyeztetés során (a hívások Deconstruct, a tulajdonsághozzáférések és a tagok meghívásai System.Runtime.CompilerServices.ITuple).
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
;
Egy simple_designation felismerésekor, ha a discard_designation és single_variable_designation alternatíva is alkalmazható, akkor az előbbit kell választani.
Megjegyzés: Az ANTLR automatikusan választja a megadott lehetőséget a simple_designation alternatíváinak sorrendje miatt. végjegyzet
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 mintae is T _egyenértékű, haTnem null értékű típus. végjegyzet
Ha a minta bemeneti értéke (11.1. §) e, ha a simple_designationegy discard_designation, és elvetést jelöl (9.2.9.2. §), az e érték nem kötődik semmihez. Ellenkező esetben, ha a simple_designationegy single_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.
Megjegyzés: A declaration_pattern ezen kezelése
_eltér a mintaként írt önálló_típustól (11.2.7.§): az utóbbi esetben a hatókörön belüli állandó vagy típus neve_– ha van ilyen – nem rejtett. végjegyzet
A típusnak E a típussal Tkompatibilis mintának kell lennie, ha létezik identitásátalakítás, implicit vagy explicit referenciakonvertálás, dobozos átalakítás, nem dobozos átalakítás, implicit vagy explicit null értékű érték típus konvertálása a típusról a formátumra ET, vagy ha vagy ET nyitott típus (8.4.3. §). A típus T elnevezésére szolgáló deklarációs minta (11.2.1. §) minden olyan típusra Ealkalmazható, amelynek E mintája kompatibilis a .T Fordítási idejű hiba, ha egy típust T elnevező deklarációs minta egy olyan minta bemeneti értékének (11.1. §) felel meg, amelynek statikus típusa E nem kompatibilis a mintával T.
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 dobozosT) érték megfelel egy típusmintánakT2 id, ha az érték nem null értékű, ésT2azT, vagy a típus valamilyen alaptípusaTvagy felülete. Például a kódtöredékbenint? x = 3; if (x is int v) { /* code using v */ }Az utasítás állapota
iffutásidőben vantrue, és a változóva blokkon belül tárolja a típus3értékétint. A blokk után a változóvható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
Pmegfelel az e értéknek, ha a kifejezése == vtrueeredménye; egyébként - ha e típus
System.Span<char>vagySystem.ReadOnlySpan<char>, és v állandó sztring, és a v nem rendelkeziknullállandó értékkel, akkor a minta megfeleltetésnek minősül, haSystem.MemoryExtensions.SequenceEqual<char>(e, System.MemoryExtensions.AsSpan(v))visszaadjatrue; ellenkező esetben - a minta
Pmegfelel az e értéknek, haobject.Equals(e, v)visszaadjatrue.
Példa: A
switchkö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, kiolvas egy értéksorozatot belőle, és megfelel az egyes kinyert értékeknek egy megfelelő alpatteren. Az értékek kinyerése háromféleképpen történik: a bemenetet rekordként kezeli, metódus meghívásával Deconstruct vagy a bemenet System.Runtime.CompilerServices.ITupleindexelésével.
Megjegyzés: Az itt használt
Deconstructadatok eltérnek a 12.7. végjegyzet
positional_pattern
: type? '(' subpatterns? ')' property_subpattern? simple_designation?
;
subpatterns
: subpattern (',' subpattern)*
;
subpattern
: pattern
| subpattern_name ':' pattern
;
subpattern_name
: identifier
| subpattern_name '.' identifier
;
Legyen n a zárójelek között megjelenő alpatterekszáma. Az egyező stratégia fordításkor van kiválasztva a következő esetek sorrendjének alkalmazásával; az első eset, amelynek feltételei teljesülnek, és a fennmaradó eseteket nem veszik figyelembe. Az eset kiválasztása után a stratégia véglegesítése megtörténik: az ebben az esetben megadott fordítási idő hibát a program jelenti, és az egyeztetés nem kerül át egy későbbi esetre.
- Rekordforma. Ha a típus nincs megadva, és a bemeneti érték statikus típusa rekordtípus (8.3.11. §), vagy ha a bemeneti érték egy rekordkonstans (12.8.6. §), akkor ez az eset érvényes. Fordítási idő hiba, ha n nem egyenlő az adott típus aritásával. Futásidőben a rendszer minden egyes elemet egyeztet a megfelelő alhálózattal; az egyezés sikeres lesz, ha ezek mindegyike sikeres. Ha bármely alpattern rendelkezik azonosítóval, az azonosítónak el kell neveznie a tuple elemet a típus megfelelő helyén.
- Deconstruct form. Ellenkező esetben, ha valamelyik típus jelen van, vagy a típus ki van hagyva, és a bemeneti érték statikus típusa tartalmaz egy akadálymentes
Deconstructmódszert (12.7. §), akkor ez az eset érvényes. Írja be a Dtípust , ha a típus jelen van; egyéb esetben hagyja , hogy a D legyen a bemeneti érték statikus típusa. ADeconstructD-ből a dekonstruálási deklarációhoz hasonló túlterhelésfeloldási szabályokkal választunk ki egy metódust, azzal a további követelménysel, hogy a paraméterek számaoutn-vel egyenlő legyen; fordítási idő hiba, ha nincs ilyen módszer. Ha a típus jelen van, akkor fordítási idejű hiba, ha a bemeneti érték statikus típusa nem mintával kompatibilis (11.2.2.2. §) típussal; futásidőben a bemeneti érték típus alapján van tesztelve, és ha a teszt sikertelen, a pozícióminta egyezése meghiúsul. Ellenkező esetben a bemeneti érték D értékké alakul, és a rendszer meghívja a kiválasztottDeconstructmetódust a paramétereket fogadóoutfriss változókkal. Minden fogadott érték megfelel a megfelelő alhálózatnak, és az egyezés sikeres lesz, ha ezek mindegyike sikeres. Ha bármely alhálózat rendelkezik azonosítóval, az azonosítónak a paramétert a megfelelő pozícióban kell megadniaDeconstruct. - ITuple űrlap. Ellenkező esetben, ha a típus nincs megadva, egyetlen alpatter sem rendelkezik azonosítóval, és a bemeneti érték
objectstatikus típusa ,System.Runtime.CompilerServices.ITuplevagy egy olyan típus, amely implicit hivatkozási konverzióvalSystem.Runtime.CompilerServices.ITuplerendelkezik, akkor ez az eset érvényes. Futásidőben a bemeneti érték tesztelésenullSystem.Runtime.CompilerServices.ITuplenem a következő: ha a teszt sikertelen, a pozícióminta egyezése meghiúsul. Ellenkező esetben az érték tulajdonságaLengthbeolvasva, és ha nem egyenlő n értékkel, a pozícióminta egyezése meghiúsul. Ellenkező esetben minden i 1-től n-ig, a bemeneti érték i − 1 értékkel való indexelésével kapott érték az i-edikallaphoz van igazítva, és az egyezés sikeres lesz, ha mindegyik sikeres. - Ellenkező esetben nincs eset, és a positional_pattern fordítási idő 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 60zá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
snem 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őhiba, ha az e kifejezés nem mintával kompatibilis (11.2.2.2. §) a típus szerint kijelölt T típussal. 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 abczá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
: '_'
;
Ha a szintaktikai környezet lehetővé teszi a mintát, ha a jogkivonat _simple_name (12.8.4. §) feloldana egy akadálymentes állandóra vagy egy típusra, akkor _a rendszer nem kezeli discard_pattern. Helyette:
- Ha
_akadálymentes állandóra van feloldva, a_rendszer constant_pattern (11.2.3. §) értelmezi, amelynek állandókifejezése ez az állandó. - Ha
_egy típusra van feloldva, akkor az operátor jobb oldalánisa szerkezet relational_expressionis _is-type operátorként (12.15.12.1.1.1.) értelmezi a rendszer az adott típuson végzett tesztelést. Bármely más szintaktikai kontextusban, amely elismeri a mintát,_a típus nélküli feloldás önmagában nem érvényes minta, azonban előfordulhat,_hogy egy declaration_patterntípusaként (például_ x) vagy más, típusnak kifejezetten nevező mintaformákban jelenik meg.
Ez a szabály megőrzi a visszafelé kompatibilitást az elvetési minta bevezetése előtt típusként vagy azonosítóként definiált _ kóddal. Ha _ nem akadálymentes állandóra vagy típusra (például helyi változóra, paraméterre, mezőre vagy metódusra) oldja fel a megoldást, a szabály nem érvényes, és _discard_pattern marad.
Megjegyzés: Ez hasonló a 11.2.4. §-ban szereplő szabályhoz
var, azzal a kivételrel, hogy_a hatókörön belüli állandó vagy típus esetében a hiba helyett az adott_deklarációra mutató hivatkozásként kell értelmezni. végjegyzet
Ha az előző szabály alkalmazása után a jogkivonat _ továbbra is discard_pattern, akkor fordítási időhiba, hogy a discard_patternaz űrlapis relational_expressionmintarelational_expression teljes mintájaként vagy egy switch_label teljes mintájaként jelenik meg. A discard_pattern azonban egy beágyazási minta alpatterjeként is megjelenhetnek (például egy positional_pattern vagy property_patternalpatterjeként).
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.0Itt egy elvetési mintát használunk a kezeléshez
null, és minden olyan egész számértéket, amely nem rendelkezik azDayOfWeekenumerálás megfelelő tagjával. Ez garantálja, hogy aswitchkifejezés minden lehetséges bemeneti értéket kezel. záró példa
Példa: Az alábbiak azt szemléltetik, hogy a hatókörön belüli konstans neve
_hogyan változtatja meg egy_kar értelmezését egyswitchkifejezésben. AWithoutUnderscorekar_egy discard_pattern , és minden értéknek megfelel. EbbenWithUnderscoreaz esetben a hatókörön belüli állandó_miatt a_kar olyan constant_pattern lesz értelmezve, amely csak az értéknek0felel meg .static string WithoutUnderscore(int n) => n switch { 1 => "one", _ => "other", }; static string WithUnderscore(int n) { const int _ = 0; return n switch { 1 => "one", _ => "zero", var x => "other: " + x, }; }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
Fordítási időhiba, ha constant_expression, double.NaNfloat.NaNvagy null_literal.
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 a constant_expression típusává lesz konvertálva explicit null értékű vagy nem dobozos átalakítással. Fordítási idejű hiba, ha nincs ilyen átalakítás. Fordítási idejű hiba, ha a bemeneti típus egy olyan típusparaméter, amely korlátozott vagy egy típus öröklődik, System.Numerics.INumberBase<T> és a bemeneti típus nem rendelkezik megfelelő beépített bináris relációs operátor definiálásával. 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 a constant_expression.
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 Acceptablezá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
notorlehet 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
Ptípusminta, akkor a szűkített típus a típusminta típusának típusa. - Ellenkező esetben, ha
Pdeklarációs minta, a szűkített típus a deklarációs minta típusának típusa. - Ellenkező esetben, ha
Pegy rekurzív minta explicit típust ad, akkor a leszűkített típus az a típus. - Ellenkező esetben, ha
PegyITupleszabályai (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
Polyan 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
Pmintaor, 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ánakorösszes alpatterét (figyelmen kívül hagyva a zárójeles mintákat). - Ellenkező esetben, ha
Pmintaand, 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ípus
PaPbemeneti típus.
Megjegyzés: Ahogy a nyelvtan is jelzi,
notelső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 Acceptablezá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 springzá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: Truezáró példa
11.2.11 Listaminta
A list_pattern egy lista vagy tömb elemeinek sorozatával egyezik.
list_pattern
: list_pattern_clause simple_designation?
;
list_pattern_clause
: '[' (pattern (',' pattern)* ','?)? ']'
;
A list_pattern kompatibilis minden olyan típussal, amely megszámlálható (18.1. §) és indexelhető (18.1. §) – olyan akadálymentes indexelővel rendelkezik, amely argumentumként, Index vagy egy egyetlen int paraméterrel rendelkező akadálymentes indexelővel rendelkezik. Ha mindkét indexelő jelen van, az előbbi előnyben részesül. (Az implicit indextámogatás részleteiért lásd a 18.4.2. cikket .)
Az űrlap expr is [1, 2, 3] mintája megegyezik a következő kóddal:
expr.Length is 3
&& expr[new Index(0, fromEnd: false)] is 1
&& expr[new Index(1, fromEnd: false)] is 2
&& expr[new Index(2, fromEnd: false)] is 3
Példa:
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 and not 7]); // Truezáró példa
Az elvetési minta (11.2.7. §) egyetlen elemnek felel meg.
Példa:
List<int> numbers = new() { 1, 2, 3 }; if (numbers is [_, var second, _]) { Console.WriteLine($"The second element is {second}."); }záró példa
11.2.12 Szeletminta
Egy slice_pattern nullát vagy több elemet elvet. Közvetlenül csak egy list_pattern_clause szabad használni, és ebben a záradékban legfeljebb egyszer.
slice_pattern
: '..' pattern?
;
Az alpatter nélküli slice_pattern kompatibilis minden olyan típussal, amely kompatibilis a list_pattern. Az alpatternnel rendelkező slice_pattern kompatibilis minden olyan típussal, amely megszámlálható (18.1. §) és szeletelhető (18.1. §) – egy akadálymentes indexelővel rendelkezik, amely Range argumentumként, vagy két Slice paraméterrel rendelkező akadálymentes int metódussal rendelkezik. Ha mindkettő jelen van, az előbbi előnyben részesül. (Az implicit indextámogatás részleteiért lásd a 18.4.2. cikket .)
A slice_pattern úgy viselkednek, mint egy megfelelő elvetés; azaz ilyen mintát nem lehet tesztelni. Ehelyett csak a többi csomópontot, nevezetesen a hosszt és az indexelőt érinti. Az űrlap expr is [1, .. var s, 3] mintája például egyenértékű a következő kóddal (ha explicit Index és Range támogatással kompatibilis):
expr.Length is >= 2
&& expr[new Index(0, fromEnd: false)] is 1
&& expr[new Range(new Index(1, fromEnd: false), new Index(1, fromEnd: true))] is var s
&& expr[new Index(1, fromEnd: true)] is 3
A slice_pattern bemeneti típusa az alapul szolgáló this[Range] vagy Slice metódus visszatérési típusa két kivétellel: s és tömbök esetén string, string.Substring illetve RuntimeHelpers.GetSubArraytömbök esetén.
Példa: A szeletminta csak a bemeneti sorozat elején vagy végén használható elemek egyeztetésére.
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]); // Falsezáró példa
Példa: Egy alpattern egy szeletmintában ágyazható be:
MatchMessage("aBBA"); // output: Message aBBA matches; inner part is BB. MatchMessage("apron"); // output: Message apron doesn't match. 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); } Validate(new[] { -1, 0, 1 }); // output: not valid Validate(new[] { -1, 0, 0, 1 }); // output: valid void Validate(int[] numbers) { var result = numbers is [< 0, .. { Length: 2 or 4 }, > 0] ? "valid" : "not valid"; Console.WriteLine(result); }záró példa
11.3 Minta-részsumpció
Egy kapcsolóutasításban (13.8.3. §) hiba, ha egy eset mintáját az előző, nem őrzött esetek halmaza (13.8.3. §) aláveti. Egy kapcsolókifejezésben (12.12.§) hiba, ha egy switch_expression_arm mintáját az előző, nem őrzöttswitch_expression_armmintái alávetik.
Megjegyzés: Ez azt jelenti, hogy a bemeneti értékeket az előző esetek vagy karok egyikével egyeztették volna. végjegyzet 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. -
Pegy type_pattern a típushozT, ésKnemnull, és a futtatókörnyezet típusaKszármazikTTvagy egy implementáltTtípus. -
Pegy relational_pattern az "op" operátorral és az állandóvalv, és az "op"Kkifejezésvkiértékelése a következő lesztrue: . -
Pegy negated_patternnot P₁, ésP₁nem egyezikK. -
Pegy conjunctive_patternP₁ and P₂, és mindkettőP₁egyezikK, ésP₂megfelelneK. -
Pegy disjunctive_patternP₁ or P₂, és vagyP₁egyezikKvagyP₂egyezikK. -
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észletQbármely mintája megegyezikPa konvertált értékével -
Pegy var minta, és a mintákQké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 mintaQegyeziknull. -
Pegy típussalTrendelkező deklarációsQminta, és a minták készlete teljes a típusraTvonatkozóan (11.4. §). -
Ptype_pattern a típushozT, és a mintákQteljes halmaza a típushozTtartozik. -
Pegy relational_pattern az "op" operátorral és az állandó értékkelv, és a bemeneti típus minden olyan értékéhez, amely megfelel az "op"vrelációnak, a készletQegy bizonyos mintája megfelelne ennek az értéknek. -
Pa disjunctive_patternP₁ or P₂és a mintákQalösszegeinekP₁ésQalösszegeinek halmazaP₂. -
Pegy conjunctive_patternP₁ and P₂, és legalább az alábbiak egyikét tartalmazza:QalösszegekP₁vagyQalösszegekP₂. -
Pegy negated_patternnot P₁, ésQa bemeneti típus teljes körű , figyelembe véve csak azokat az értékeket, amelyeketP₁nem egyeznek meg. -
Pegy discard_pattern , és a mintákQké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 mintaQegyeziknull. - Néhány minta
Qegy disjunctive_patternQ₁ or Q₂, és ha ezt a mintát in értékreQ₁Qcserélné , az olyan készletet eredményezne, amely alösszegeketPeredményezne , vagy ha lecserélné aztQ₂, akkor ez az alösszegekPhalmazt eredményezne . - Egyes minták
Qnegated_patternnot Q₁, ésPnem egyeznek meg egyetlen értékkelQ₁sem.
Példa: A következő kapcsolókifejezésben egyetlen kar sem lesz alárendelve, annak ellenére, hogy az 1., 2. és 3. kar ugyanazzal a mintával rendelkezik:
object x = 10; bool b = false; int y = x switch { int i when !b => 0, int i when b => 1, int i => 2, _ => 3 };Az 1. és a 2. kar nem állandó védőburkolatokkal rendelkezik, és így nem őrzetlenek; csak a 3. kar van őrizetlen mintával
int i, ami nem alösszegezi a végső_kart, mert nem egyezik meg egy nem-értékint, példáulnull. záró példa
Az list_patternés a slice_patternalegységeinek szubsumpciós ellenőrzése ugyanúgy működik, mint a (ITuple-ös megfelelő alhálózatokkal rendelkező pozícióminták, valamint a tesztelési hosszhoz szükséges további csomópontok.
A következő kód például hibát okoz, mert mindkét minta ugyanazt a DAG-ot eredményezi:
case [_, .., 1]: // expr.Length is >= 2 && expr[^1] is 1
case [.., _, 1]: // expr.Length is >= 2 && expr[^1] is 1
Ellentétben:
case [_, 1, ..]: // expr.Length is >= 2 && expr[1] is 1
case [.., 1, _]: // expr.Length is >= 2 && expr[^2] is 1
Adott hossz esetén lehetséges, hogy két alpatter ugyanarra az elemre hivatkozik, ebben az esetben az érték tesztelése be lesz szúrva a döntési DAG-ba.
- A 3-nak például az a helye,
[_, >0, ..] or [.., <=0, _]length >= 2 && ([1] > 0 || length == 3 || [^2] <= 0)ahol a 3 hosszúsági érték a másik tesztet jelenti. - Ezzel szemben
[_, >0, ..] and [.., <=0, _]length >= 2 && [1] > 0 && length != 3 && [^2] <= 0a 3 hosszúsági érték nem engedélyezi a másik tesztet.
Ennek eredményeképpen hiba fog következni valami hasonló case [.., p]: case [p]: miatt, mert futásidőben ugyanazt az elemet egyezteti a második esetben.
Ha egy szelet allapja megfelel egy listának vagy egy hosszértéknek, az alpattereket úgy kell kezelni, mintha azok a lista közvetlen alpatterei lennének. Például [..[1, 2, 3]] az űrlap [1, 2, 3]egy mintáját alösszegezi.
A használt tagokra a következő feltételezések épülnek:
- A típust megszámláló tulajdonságot feltételezzük, hogy mindig nem negatív értéket ad vissza, ha és csak akkor, ha a típus indexelhető. A minta
{ Length: -1 }például soha nem egyezhet meg tömbökben. - Az a tag, amely szeletelhetővé teszi a típust, feltételezzük, hogy megfelelően viselkedik; azaz a visszatérési érték soha nem
null, és hogy az a tartalmazó lista megfelelő alosztálya.
A mintaegyeztetési művelet viselkedése nem határozható meg, ha a fenti feltételezések közül bármelyik nem áll fenn. [
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:
-
Tegy 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éhezTbizonyos mintaQmegfelelne ennek az értéknek; vagy - Néhány minta
Qegy var minta; vagy - A minta
Qegy típusD, és van egy identitáskonverzió, egy implicit referenciakonvertálás, vagy egy dobozos átalakítás a típusrólTD; vagy - A minta
Qegy type_pattern típushozD, és van egy identitáskonverzió, egy implicit referenciakonvertálás, vagy egy keretkonvertálás a típusrólTDaz ; vagy - Néhány minta
Qegy discard_pattern; vagy - 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étT.floatAdoublerelációs mintával nem egyezik meg; vagySystem.Double.NaNnem felel meg a relációsSystem.Single.NaNmintának,NaNvagy - Néhány minta
Qegy disjunctive_patternP₁ or P₂, és felváltja ezt a mintát mindP₁aP₂Qhozamok egy készlet, amely kimerítőT; vagy - Néhány minta
Qegy negated_patternnot P₁, és a mintákQa nem egyezőP₁értékekkel együtt lefedik a lehetséges értékeketT. A negated_patternnot P₁önmagában teljes körű, haP₁nem felel meg azT; vagy - Néhány minta
Qegy conjunctive_patternP₁ and P₂, és a csakP₁a teljesTértéket tartalmazó készlet teljes, és a csakP₂a teljes halmaztTtartalmazza.
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>= 0kombinációja nem teljes, mert egyik relációs minta sem egyezikNaN. A teljesség igénye a következő lenne< 0: ,>= 0ésdouble.NaN(vagyfloat.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
ECMA C# draft specification