Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
11.1 Allmänt
Ett mönster är en syntaktisk form som kan användas med operatorn is (§12.15.12), i en switch_statement (§13.8.3) och i en switch_expression (§12.12) för att uttrycka formen på data som inkommande data ska jämföras med. Mönster kan vara rekursiva, så att delar av data kan matchas mot undermönster.
Ett mönster testas mot ett värde i ett antal kontexter:
- I en switch-instruktion testas mönstret för en ärendeetikett mot uttrycket för switch-instruktionen.
- I en is-pattern-operator testas mönstret till höger mot uttrycket till vänster.
- I ett växeluttryck testas mönstret för en switch_expression_arm mot uttrycket på växeluttryckets vänstra sida.
- I kapslade kontexter testas undermönstret mot värden som hämtats från egenskaper, fält eller indexeras från andra indatavärden, beroende på mönsterformuläret.
Värdet som ett mönster testas mot kallas mönsterindatavärdet.
11.2 Mönsterformulär
11.2.1 Allmänt
Ett mönster kan ha något av följande formulär:
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 ')'
;
Produktionen '(' pattern ')' gör att ett mönster kan omges av parenteser för att framtvinga utvärderingsordningen mellan mönster som kombineras med någon av de logical_patterns.
Vissa mönsterkan resultera i deklarationen av en lokal variabel.
Varje mönsterformulär definierar uppsättningen med typer för indatavärden som mönstret kan tillämpas på. Ett mönster P gäller för en typ T om T är bland de typer vars värden mönstret kan matcha. Det är ett kompileringsfel om ett mönster P visas i ett program för att matcha ett mönsterindatavärde (§11.1) av typen T om P det inte är tillämpligt på T.
Exempel: I följande exempel genereras ett kompileringsfel eftersom kompileringstidstypen
värTextReader. En variabel av typenTextReaderkan aldrig ha ett värde som är referenskompatibelt medstring:TextReader v = Console.In; // compile-time type of 'v' is 'TextReader' if (v is string) // compile-time error { // code assuming v is a string }Följande genererar dock inte ett kompileringsfel eftersom kompileringstidstypen
värobject. En variabel av typenobjectkan ha ett värde som är referenskompatibelt medstring:object v = Console.In; if (v is string s) { // code assuming v is a string }slutexempel
Varje mönsterformulär definierar den uppsättning värden som mönstret matchar värdet för vid körning.
Ordningen för utvärdering av åtgärder och biverkningar under mönstermatchning (anrop till Deconstruct, egenskapsåtkomster och anrop av metoder i System.ITuple) har inte angetts.
11.2.2 Deklarationsmönster
En declaration_pattern används för att testa att ett värde har en viss typ och, om testet lyckas, om du vill ange värdet i en variabel av den typen.
declaration_pattern
: type simple_designation
;
simple_designation
: discard_designation
| single_variable_designation
;
discard_designation
: '_'
;
single_variable_designation
: identifier
;
En simple_designation med token _ ska betraktas som en discard_designation snarare än en single_variable_designation.
Körningstypen för värdet testas mot typen i mönstret med samma regler som anges i operatorn is-type (§12.15.12.1). Om testet lyckas matchar mönstret det värdet. Det är ett kompileringsfel om typen är en nullbar värdetyp (§8.3.12) eller en nullbar referenstyp (§8.9.3). Det här mönsterformuläret matchar aldrig ett null värde.
Obs! Uttrycket
e is Tis-type och deklarationsmönstrete is T _är likvärdiga närTdet inte är en nullbar typ. slutkommentar
Med tanke på ett mönsterindatavärde (§11.1) e, om simple_designation är discard_designation, anger det ett ignorerande (§9.2.9.2), och värdet på e är inte bundet till någonting. (Även om en deklarerad variabel med namnet _ kan finnas i omfånget vid den tidpunkten visas inte den namngivna variabeln i den här kontexten.) Om simple_designation annars är single_variable_designation introduceras en lokal variabel (§9.2.9) av den angivna typen som namnges av den angivna identifieraren. Den lokala variabeln tilldelas värdet för mönsterindatavärdet när mönstret matchar värdet.
Vissa kombinationer av statisk typ av mönsterindatavärdet och den angivna typen anses vara inkompatibla och resulterar i ett kompileringsfel. Ett värde av statisk typ E sägs vara mönsterkompatibelt med typen T om det finns en identitetskonvertering, en implicit eller explicit referenskonvertering, en boxningskonvertering, en konvertering utan inkorg eller en implicit eller explicit nullbar värdetypskonvertering från E till T, eller om antingen E eller T är en öppen typ (§8.4.3). Ett deklarationsmönster som namnger en typ gäller för varje typ T som är mönsterkompatibel med E.ET
Obs! Stödet för öppna typer kan vara mest användbart när du kontrollerar typer som kan vara antingen struct- eller klasstyper, och boxning bör undvikas. slutkommentar
Exempel: Deklarationsmönstret är användbart för att utföra körningstyptester av referenstyper och ersätter formspråket
var v = expr as Type; if (v != null) { /* code using v */ }med den något mer koncisa
if (expr is Type v) { /* code using v */ }slutexempel
Exempel: Deklarationsmönstret kan användas för att testa värden för null-typer: ett värde av typen
Nullable<T>(eller en rutadT) matchar ett typmönsterT2 idom värdet inte är null ochT2ärT, eller någon bastyp eller gränssnitt förT. Till exempel i kodfragmentetint? x = 3; if (x is int v) { /* code using v */ }Villkoret för -instruktionen
ifärtruevid körning och variabelnvinnehåller värdet3av typeninti blocket. Efter blocket är variabelnvi omfånget, men inte definitivt tilldelad. slutexempel
11.2.3 Konstant mönster
En constant_pattern används för att testa värdet för ett mönsterindatavärde (§11.1) mot det angivna konstantvärdet.
constant_pattern
: constant_expression
;
Ett konstant mönster P gäller för en typ T om det finns en implicit konvertering från det konstanta uttrycket för P till typen T.
För ett konstant mönster Pär dess konverterade värde
- Om mönstrets indatavärdestyp är en integraltyp eller en uppräkningstyp konverteras mönstrets konstantvärde till den typen. annars
- Om mönstrets indatavärdestyp är den nullbara versionen av en integraltyp eller en uppräkningstyp konverteras mönstrets konstantvärde till dess underliggande typ. annars
- värdet för mönstrets konstanta värde.
Givet ett mönsterindatavärde e och ett konstant mönster P med konverterat värde v,
- om e har en integraltyp eller uppräkningstyp, eller en nullbar form av en av dessa, och v har en integrerad typ, matchar mönstret
Pvärdet e om resultatet av uttryckete == värtrue, annars - mönstret
Pmatchar värdet e omobject.Equals(e, v)returnerartrue.
Exempel: Instruktionen
switchi följande metod använder fem konstanta mönster i sina skiftlägesetiketter.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(...); } }slutexempel
11.2.4 Var-mönster
Ett var_patternmatchar varje värde. En mönstermatchningsåtgärd med en var_pattern lyckas alltså alltid.
En var_pattern gäller för varje typ.
var_pattern
: 'var' designation
;
designation
: simple_designation
| tuple_designation
;
tuple_designation
: '(' designations? ')'
;
designations
: designation (',' designation)*
;
Givet ett mönstrat indatavärde (§11.1) e, om beteckningenär discard_designation, det antecknar en kassera (§9.2.9.2), och värdera av e är inte bundet till något. (Även om en deklarerad variabel med det namnet kan finnas i omfånget vid den tidpunkten visas inte den namngivna variabeln i den här kontexten.) Annars, om beteckningenär single_variable_designation, vid körning är värdet e bundet till en nyligen introducerad lokal variabel (§9.2.9) av det namnet vars typ är den statiska typen av e, och mönstrets indatavärde tilldelas till den lokala variabeln.
Det är ett fel om namnet var skulle binda till en typ där en var_pattern används.
Om beteckning är en tuple_designation, är mönstret likvärdigt med en positional_pattern (§11.2.5) av (var, ...
) där beteckningenär de som finns inom tuple_designation. Mönstret var (x, (y, z)) motsvarar till (var x, (var y, var z))exempel .
11.2.5 Positionsmönster
En positional_pattern kontrollerar att indatavärdet inte nullär , anropar en lämplig Deconstruct metod (§12.7) och utför ytterligare mönstermatchning på de resulterande värdena. Den stöder också en tupplarliknande mönstersyntax (utan att typen anges) när typen av indatavärde är samma som typen som innehåller Deconstruct, eller om typen av indatavärde är en tupplartyp, eller om typen av indatavärde är object eller System.ITuple och körningstypen för uttrycket implementerar System.ITuple.
positional_pattern
: type? '(' subpatterns? ')' property_subpattern? simple_designation?
;
subpatterns
: subpattern (',' subpattern)*
;
subpattern
: pattern
| identifier ':' pattern
;
Med tanke på en matchning av ett indatavärde med mönstertypens(undermönster), väljs en metod genom att söka i typ efter tillgängliga deklarationer av Deconstruct och välja en av dem med samma regler som för dekonstruktionsdeklarationen.
Det är ett fel om en positional_pattern utelämnar typen, har ett enda undermönster utan identifierare, inte har någon property_subpattern och inte har någon simple_designation. Detta skiljer sig mellan en constant_pattern som är parentesiserad och en positional_pattern.
För att extrahera de värden som ska matchas mot mönstren i listan,
- Om typen utelämnas och indatauttryckets typ är en tuppelns typ, ska antalet undermönster vara detsamma som tuppelns kardinalitet. Varje tuppelns element matchas mot motsvarande underavsnitt och matchningen lyckas om alla dessa lyckas. Om någon underordnad har en identifierare, ska det namnge ett tupppelelement vid motsvarande position i tuppelns typ.
- Om en lämplig
Deconstructfinns som medlem av typen är det annars ett kompileringsfel om typen av indatavärde inte är mönsterkompatibel med typen. Vid körning testas indatavärdet mot typ. Om detta misslyckas misslyckas positionsmönstermatchningen. Om det lyckas konverteras indatavärdet till den här typen ochDeconstructanropas med nya kompilatorgenererade variabler för att ta emot utdataparametrarna. Varje värde som togs emot matchas mot motsvarande undermönster och matchningen lyckas om alla dessa lyckas. Om någon underordnad har en identifierare ska den ge en parameter namnet på motsvarande positionDeconstruct. - Annars, om typen utelämnas och indatavärdet är av typen
objecteller någon typ som kan konverteras tillSystem.ITupleav en implicit referenskonvertering, och ingen identifierare visas bland underavsnitten, använderSystem.ITuplematchningen . - Annars är mönstret ett kompileringsfel.
Ordningen i vilken underavsnitt matchas vid körning är ospecificerad och en misslyckad matchning kanske inte försöker matcha alla undermönster.
Exempel: Här dekonstruerar vi ett uttrycksresultat och matchar de resulterande värdena mot motsvarande kapslade mönster:
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); }slutexempel
Exempel: Namnen på tuppelns element och dekonstruktionsparametrar kan användas i ett positionsmönster enligt följande:
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); }De utdata som genereras är
Sum of [10 20 30] is 60slutexempel
11.2.6 Egenskapsmönster
En property_pattern kontrollerar att indatavärdet inte nullär och matchar rekursivt värden som extraheras med hjälp av tillgängliga egenskaper eller fält.
property_pattern
: type? property_subpattern simple_designation?
;
property_subpattern
: '{' '}'
| '{' subpatterns ','? '}'
;
Det är ett fel om ett underavsnitt av en property_pattern inte innehåller någon identifierare.
Det är ett kompileringsfel om typen är en nullbar värdetyp (§8.3.12) eller en nullbar referenstyp (§8.9.3).
Obs! Ett null-kontrollmönster faller ur ett trivialt egenskapsmönster. För att kontrollera om strängen
sinte är null kan man skriva något av följande formulär:#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 {}) ...slutkommentar
Med tanke på en matchning av ett uttryck e tillunderordnad{mönstertyp} är det ett kompileringsfel om uttrycket e inte är mönsterkompatibelt med typen T som har angetts efter typ. Om typen saknas antas typen vara den statiska typen e. Var och en av de identifierare som förekommer till vänster om dess underordnad ska ange en tillgänglig läsbar egenskap eller ett fält i T. Om simple_designation för property_pattern finns deklarerar den en mönstervariabel av typen T.
Vid körning testas uttrycket mot T. Om detta misslyckas misslyckas egenskapsmönstermatchningen och resultatet blir false. Om det lyckas läss varje property_subpattern fält eller egenskap och dess värde matchas mot motsvarande mönster. Resultatet av hela matchningen är false bara om resultatet av något av dessa är false. Ordningen där undermönster matchas anges inte och en misslyckad matchning kanske inte testar alla undermönster vid körning. Om matchningen lyckas och simple_designation för property_pattern är en single_variable_designation tilldelas den deklarerade variabeln det matchade värdet.
Property_pattern kan användas för att mönstermatcha med anonyma typer.
Exempel:
var o = ...; if (o is string { Length: 5 } s) ...slutexempel
Exempel: En körningstypkontroll och en variabeldeklaration kan läggas till i ett egenskapsmönster enligt följande:
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."), };De utdata som genereras är
Hello Hi! 12345 abcslutexempel
11.2.7 Ignorera mönster
Varje uttryck matchar mönstret ignorera, vilket resulterar i värdet för uttrycket som ignoreras.
discard_pattern
: '_'
;
Det är ett kompileringsfel att använda ett ignorerande mönster i en relational_expression av formuläret relational_expressionismönster eller som mönstret för en switch_label.
Obs! Om du vill matcha alla uttryck använder du en var_pattern med ignorera
var _. slutkommentar
Exempel:
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, };De utdata som genereras är
5.0 0.0 0.0Här används ett ignorerande mönster för att hantera
nulloch alla heltalsvärden som inte har motsvarande medlem iDayOfWeekuppräkningen. Det garanterar att uttrycketswitchhanterar alla möjliga indatavärden. slutexempel
11.2.8 Typmönster
En type_pattern används för att testa att indatavärdet för mönster (§11.1) har en viss typ.
type_pattern
: type
;
Ett typmönster som namnger en typ Tgäller för varje typ E som E är mönsterkompatibel med T (§11.2.2).
Körningstypen för värdet testas mot typen med samma regler som anges i is-type-operatorn (§12.15.12.1). Om testet lyckas matchar mönstret det värdet. Det är ett kompileringsfel om typen är en nullbar typ. Det här mönsterformuläret matchar aldrig ett null värde.
11.2.9 Relationsmönster
En relational_pattern används för att relationstesta mönsterindatavärdet (§11.1) mot ett konstant värde.
relational_pattern
: '<' relational_expression
| '<=' relational_expression
| '>' relational_expression
| '>=' relational_expression
;
Relational_expression i en relational_pattern krävs för att utvärdera till ett konstant värde.
Relationsmönster stöder relationsoperatorerna , , och på alla inbyggda typer som stöder sådana binära relationsoperatorer med samma typ: sbyte, byte, short, ushort, int, uint, doubledecimalcharulongfloatlong, nint, nuintoch uppräkningar.>=><=<
En relational_patterngäller för en typ T om en lämplig inbyggd binär relationsoperator definieras med båda operanderna av typen T, eller om det finns en explicit nullbar konvertering eller avboxningskonvertering från T till typen av konstantuttryck.
Det är ett kompileringsfel om uttrycket utvärderas till double.NaN, float.NaNeller en null-konstant.
När indatavärdet har en typ för vilken en lämplig inbyggd binär relationsoperator definieras, tas utvärderingen av operatorn som innebörden av relationsmönstret. Annars konverteras indatavärdet till typen av konstant uttryck med hjälp av en explicit nullbar eller avboxningskonvertering. Det är ett kompileringsfel om det inte finns någon sådan konvertering. Mönstret anses inte matcha om konverteringen misslyckas. Om konverteringen lyckas är resultatet av mönstermatchningsåtgärden resultatet av utvärderingen av uttrycket e «op» v där e är de konverterade indata, «op» är relationsoperatorn och v är det konstanta uttrycket.
Exempel:
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", };De utdata som genereras är
Too high Unknown Acceptableslutexempel
11.2.10 Logiskt mönster
En logical_pattern används för att negera resultatet av en mönstermatchning, eller för att kombinera resultatet av flera mönstermatchningar med hjälp av konjunktion (and) eller disjunction (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, andoch or kallas tillsammans för mönsteroperatorer.
Ett negated_pattern matchar om mönstret som negeras inte matchar, och vice versa. En conjunctive_pattern kräver att båda mönstren matchar. Ett disjunctive_pattern kräver endera mönstret för att matcha. Till skillnad från deras språkoperatormotsvarigheter och &&||, and och or är inte kortslutningsoperatorer.
Det är ett kompileringsfel för en mönstervariabel som ska deklareras under en not operator eller or mönsteroperator.
Obs! Eftersom varken
notellerorkan generera en bestämd tilldelning för en mönstervariabel är det ett fel att deklarera en i dessa positioner. slutkommentar
I en conjunctive_pattern begränsas indatatypen för det andra mönstret av typen som begränsar kraven för det första mönstret i and. Den begränsade typen av ett mönster P definieras på följande sätt:
- Om
Pär ett typmönster är den begränsade typen typen av typmönstertyp. - Annars, om
Pär ett deklarationsmönster , är den smala typen typen av deklarationsmönstrets typ. - Annars, om
Pär ett rekursivt mönster som ger en explicit typ, är den smala typen den typen. - Annars, om
Pmatchas via reglerna förITuplei en positional_pattern (§11.2.5), är den smala typen typenSystem.ITuple. - Annars, om
Pär ett konstant mönster där konstanten inte är null-konstanten och uttrycket inte har någon konstant uttryckskonvertering till indatatypen, är den begränsade typen typen av konstant. - Om
Pär ett relationsmönster där konstantuttrycket inte har någon konstant uttryckskonvertering till indatatypen är den begränsade typen typen av konstant. - Annars, om
Pär ettormönster, är den smala typen den vanliga typen av den smala typen av undermönster om det finns en sådan gemensam typ. För detta ändamål tar den gemensamma typalgoritmen endast hänsyn till identitets-, boxnings- och implicita referenskonverteringar, och den tar hänsyn till alla undermönster i en sekvens avormönster (ignorerar parenteserade mönster). - Annars, om
Pär ettandmönster, är den smala typen den smala typen av rätt mönster. Dessutom är den begränsade typen av det vänstra mönstret indatatypen för det högra mönstret. - Annars är
Pden begränsade typen avPindatatyp.
Obs! Som indikeras av grammatiken
nothar företräde framförand, som har företräde framföror. Detta kan uttryckligen anges eller åsidosättas med parenteser. slutkommentar
När ett mönster visas på höger sida av isbestäms mönstrets omfattning av grammatiken, vilket innebär att mönsteroperatorerna and, oroch not inom mönstret binder hårdare än de logiska operatorerna &&, ||och ! utanför mönstret.
Exempel:
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", };De utdata som genereras är
High Too low Acceptableslutexempel
Exempel:
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}."), };De utdata som genereras är
winter autumn springslutexempel
Exempel:
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}");De utdata som genereras är
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: Trueslutexempel
11.3 Undersummor för mönster
I en switch-instruktion är det ett fel om ett ärendes mönster undersummas av föregående uppsättning obevakade ärenden (§13.8.3). Informellt innebär detta att alla indatavärden skulle ha matchats av ett av de tidigare fallen. Följande regler definierar när en uppsättning mönster undersummar ett givet mönster:
Ett mönster Pskulle matcha en konstant K om något av följande villkor gäller:
- specifikationen för det mönstrets körningsbeteende är att matchar
PK. -
Pär en type_pattern för typenTochKär intenulloch körningstypenKärTeller en typ som härleds frånTeller en typ som implementerarT. -
Pär en relational_pattern med operatorn «op» och konstantv, och uttrycketK«op»vskulle utvärderas tilltrue. -
Pär en negated_patternnot P₁ochP₁skulle inte matchaK. -
Pär en conjunctive_patternP₁ and P₂och bådaP₁matcharKochP₂skulle matchaK. -
Pär en disjunctive_patternP₁ or P₂och skulle antingenP₁matchaKellerP₂matchaK. -
Pär en discard_pattern.
En uppsättning mönster Qundersummar ett mönster P om något av följande villkor gäller:
-
Pär ett konstant mönster och något av mönstren i uppsättningenQskulle matchaPdet konverterade värdet -
Pär ett var-mönster och uppsättningen mönster är fullständig (§11.4) för typen av mönsterindatavärde (Q), och antingen är mönsterindatavärdet inte av en nullbar typ eller så matchar något mönster i .Qnull -
Pär ett deklarationsmönster med typToch uppsättningen mönsterQär fullständig för typenT(§11.4). -
Pär en type_pattern för typenToch uppsättningen mönsterQär fullständig för typenT. -
Pär en relational_pattern med operatorn «op» och konstant värdev, och för varje värde av indatatypen som uppfyller relationen «op»vskulle ett mönster i uppsättningenQmatcha det värdet. -
Pär en disjunctive_patternP₁ or P₂och en uppsättning mönsterundersummorQP₁ochQundersummorP₂. -
Pär en conjunctive_patternP₁ and P₂och minst ett av följande undantag:QundersummorP₁ellerQundersummorP₂. -
Pär en negated_patternnot P₁ochQär fullständig för indatatypen med tanke på de värden som inte matchas avP₁. -
Pär en discard_pattern och uppsättningen mönsterQär fullständig för typen av mönsterindatavärde, och antingen är mönsterindatavärdet inte av en nullbar typ eller så matcharnullnågot mönster iQ. - Vissa mönster i
Qär en disjunctive_patternQ₁ or Q₂och att ersätta det mönstret medQ₁iQskulle ge en uppsättning som undersummarPeller ersätta den medQ₂skulle ge en uppsättning som undersummorP. - Vissa mönster i
Qär en negated_patternnot Q₁ochPskulle inte matcha något värde somQ₁skulle matcha.
11.4 Mönster fullständighet
Informellt är en uppsättning mönster uttömmande för en typ om, för varje möjligt värde av den typen förutom null, något mönster i uppsättningen är tillämpligt. Följande regler definierar när en uppsättning mönster är uttömmande för en typ:
En uppsättning mönster Q är fullständig för en typ T om något av följande villkor gäller:
-
Tär en integrerad eller uppräkningstyp, eller en nullbar version av en av dessa, och för varje möjligt värde avTden underliggande typen som inte kan nollföras skulle något mönster iQmatcha det värdet, eller - Vissa mönster i
Qär ett var-mönster, eller - Ett mönster i
Qär ett deklarationsmönster för typenD, och det finns en identitetskonvertering, en implicit referenskonvertering eller en boxningskonvertering frånTtillD; eller - Vissa mönster i
Qär en type_pattern för typenD, och det finns en identitetskonvertering, en implicit referenskonvertering eller en boxningskonvertering frånTtillD; eller - Vissa mönster i
Qär en discard_pattern, eller - Mönstren i
Qinkluderar en kombination av relational_patterns och constant_patternvars intervall tillsammans täcker alla möjliga värden förTden underliggande typen som inte kan nollas. Förfloatochdoubletyper, detta inkluderarSystem.Double.NaNellerSystem.Single.NaNrespektive, eftersomNaNinte matchas av något relationsmönster; eller - Vissa mönster i
Qär en disjunctive_patternP₁ or P₂, och att ersätta det mönstret med bådeP₁ochP₂iQger en uppsättning som är fullständig förT; eller - Vissa mönster i
Qär en negated_patternnot P₁, och mönstren tillsammansQmed värdena som inte matchas avP₁täcker alla möjliga värden förT. En negated_patternnot P₁är fullständig i sig närP₁den inte matchar något möjligt värde förT; eller - Vissa mönster i
Qär en conjunctive_patternP₁ and P₂, och uppsättningen som endastP₁innehåller är fullständig förToch uppsättningen som endastP₂innehåller är fullständig förT.
Obs! När ett typmönster innehåller nullbara typer kan mönstret vara fullständigt för typen men ändå generera en varning eftersom typmönstret inte matchar ett
nullvärde. slutkommentar
Obs! För flyttalstyper är kombinationen av mönster
< 0och>= 0inte fullständig eftersom inget relationsmönster matcharNaN. En korrekt fullständig uppsättning skulle vara< 0,>= 0ochdouble.NaN(ellerfloat.NaN). slutkommentar
Exempel:
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; } }slutexempel
ECMA C# draft specification