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
A minta olyan szintaktikai forma, amely az operátorral is (12.14.12.§), egy switch_statement (13.8.3. §) és egy switch_expression (12.11. §) 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
: declaration_pattern
| constant_pattern
| var_pattern
| positional_pattern
| property_pattern
| discard_pattern
;
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é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ő simple_designationsingle_variable_designation helyett discard_designation kell tekinteni.
Az érték futtatókörnyezettípusát a rendszer a mintában szereplő típussal teszteli az is-type operátorban megadott szabályokkal (12.14.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_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 kompatibilis, ha létezik identitásátalakítás, implicit vagy explicit referenciakonvertálás, dobozos átalakítás, vagy TEha nyitott TE vagy nyitott 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 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 - 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 (varmegjelölésénekpositional_pattern (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
| identifier ':' pattern
;
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ő
Deconstructtí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, ésDeconstructa 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étertDeconstruct. - Ellenkező esetben, ha a típus nincs megadva, és a bemeneti érték típus
objectvagy 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áljaSystem.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 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 azonosítót.
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 aproperty_pattern_list
}mintatípussal{való egyezése miatt fordítási időhiba, ha az e kifejezés nem kompatibilis 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. A property_pattern_list bal oldalán megjelenő összes azonosítónak ki kell jelölnie egy hozzáférhető olvasható tulajdonságot vagy T mezőt. 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ó.
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
: '_'
;
Fordítási idő hiba az űrlapisrelational_expression 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.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
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:
A minta P akkor egyezik
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. §).
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 - Néhány minta
Qtípus , és van egy identitáskonverzió, implicit referenciaátalakítás, vagy egy dobozos átalakítás a típusrólDa másikraT.
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