11.1 常规
模式是一种语法形式,可在is(§13.8.3)和switch_expression(§12.12)中与运算符(§12.15.12)一起使用,以表达要对其比较传入数据的数据的形状。 模式可能是递归的,以便数据的各个部分可以与 子模式匹配。
针对多个上下文中的值测试模式:
- 在 switch 语句中,事例标签的 模式 根据 switch 语句的 表达式 进行测试。
- 在 is-pattern 运算符中,右侧的 模式 针对左侧的表达式进行测试。
- 在 switch 表达式中,switch_expression_arm模式针对 switch-expression 左侧的表达式进行测试。
- 在嵌套上下文中,根据模式窗体,针对从属性、字段或从其他输入值编制索引的值测试 子模式 。
对其测试模式的值称为 模式输入值。
11.2 模式窗体
11.2.1 常规
模式可能具有以下形式之一:
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 ')'
;
生产 '(' pattern ')' 允许将模式括在括号中,以强制使用 logical_pattern之一组合的模式之间的计算顺序。
某些 模式可能会导致局部变量的声明。
每个模式窗体定义可应用于该模式的输入值的类型集。 如果P模式是模式可能匹配的类型之一,则模式TT类型。 如果某个模式出现在程序中以匹配类型的P模式输入值(§11.1T如果P不适用T)。
示例:以下示例生成编译时错误,因为编译时类型
v为TextReader. 类型的TextReader变量永远不能具有与以下项兼容的string值:TextReader v = Console.In; // compile-time type of 'v' is 'TextReader' if (v is string) // compile-time error { // code assuming v is a string }但是,由于编译时类型
v为object,因此以下代码不会生成编译时错误。 类型的object变量可以具有与引用兼容的string值:object v = Console.In; if (v is string s) { // code assuming v is a string }end 示例
每个模式窗体定义模式 在运行时匹配 值的一组值。
未指定模式匹配期间对作和副作用的计算顺序(对 Deconstruct方法的 System.ITuple调用、属性访问和调用)。
11.2.2 声明模式
declaration_pattern用于测试某个值是否具有给定类型,如果测试成功,可以选择在该类型的变量中提供该值。
declaration_pattern
: type simple_designation
;
simple_designation
: discard_designation
| single_variable_designation
;
discard_designation
: '_'
;
single_variable_designation
: identifier
;
使用令牌_应被视为discard_designation而不是single_variable_designation。
值的运行时类型使用 is-type 运算符中指定的相同规则(§12.15.12.1)针对模式中的类型进行测试。 如果测试成功,则模式 与该值匹配 。 如果 类型 为可以为 null 的值类型(§8.3.12)或可为空引用类型(§8.9.3),则为编译时错误。 此模式形式永远不会与值 null 匹配。
注意:is-type 表达式
e is T,当不是可为 null 的类型时e is T _,声明模式T是等效的。 尾注
给定模式输入值 (§11.1) e,如果simple_designation discard_designation,则表示放弃(§9.2.9.2),e 的值不绑定到任何内容。 (虽然具有该名称_的声明变量可能位于该点的作用域内,但在此上下文中看不到该命名变量。否则,如果single_variable_designation simple_designation,则会引入由给定标识符命名的给定类型的局部变量(§9.2.9)。 当模式与值匹配时,向该局部变量分配模式输入值的值。
模式输入值和给定类型的静态类型的某些组合被视为不兼容,并导致编译时错误。 如果存在标识转换、隐式或显式引用转换、装箱转换、取消装箱转换或从中E转换到的隐式或显式可为 null 值类型转换,或者是否T为开放类型(E),则表示静态类型的T值与类型ET。 声明模式命名类型T适用于与该类型兼容的每种类型E。ET
注意:在检查可能为结构或类类型的类型时,对开放类型的支持最有用,并且要避免装箱。 尾注
示例:声明模式可用于执行引用类型的运行时类型测试,并替换成语
var v = expr as Type; if (v != null) { /* code using v */ }稍微简洁一点
if (expr is Type v) { /* code using v */ }end 示例
示例:声明模式可用于测试可为 null 类型的值:如果值不为 null 且
Nullable<T>T为或某些基类型或接口T2 id,则T2类型(或装箱T)的值与类型模式T匹配。 例如,在代码片段中int? x = 3; if (x is int v) { /* code using v */ }语句的条件
if在true运行时,变量v保存块内类型的3值int。 块之后,变量v位于范围内,但未明确分配。 end 示例
11.2.3 常量模式
constant_pattern用于针对给定常量值测试模式输入值(§11.1)的值。
constant_pattern
: constant_expression
;
如果存在从常量表达式P到该类型的隐式转换,则常量模式T类型P。
对于常量模式 P,其 转换的值 为
- 如果模式输入值的类型是整型类型或枚举类型,则模式的常量值转换为该类型;否则
- 如果模式输入值的类型是整型类型或枚举类型的可为 null 版本,则模式的常量值转换为其基础类型;否则
- 模式常量值的值。
给定模式输入值 e 和具有转换值 v 的常量模式P,
- 如果 e 具有整型类型或枚举类型,或其中一种可为 null 的形式,并且 v 具有整型类型,则模式
P;否则 - 如果返回,则模式
P。
示例:
switch以下方法中的语句在其事例标签中使用五个常量模式。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(...); } }end 示例
11.2.4 Var 模式
var_pattern 匹配每个值。 也就是说,具有 var_pattern 的模式匹配操作始终成功。
var_pattern适用于每种类型。
var_pattern
: 'var' designation
;
designation
: simple_designation
| tuple_designation
;
tuple_designation
: '(' designations? ')'
;
designations
: designation (',' designation)*
;
给定模式输入值(§11.1)e,如果指定为discard_designation,则表示放弃(§9.2.9.2),e 的值不绑定到任何内容。 (尽管具有该名称的声明变量可能位于该点的范围中,但在此上下文中看不到该命名变量。否则,如果指定为single_variable_designation,在运行时,e 的值将绑定到该名称的新引入局部变量(§9.2.9),其类型为 e 的静态类型,并将模式输入值分配给该局部变量。
如果名称var绑定到使用var_pattern的类型,则为错误。
如果指定为tuple_designation,则模式等效于表单指定(var(§11.2.5),...
) 其中 ,指定项是在 tuple_designation中找到的。 例如,模式 var (x, (y, z)) 等效于 (var x, (var y, var z))。
11.2.5 位置模式
positional_pattern检查输入值是否不是null,调用适当的Deconstruct方法(§12.7),并针对生成的值执行进一步的模式匹配。 如果输入值的类型与包含 Deconstruct的类型相同,或者输入值的类型是元组类型,或者输入值的类型是元组类型,或者输入值的类型是 object 或 System.ITuple 表达式 System.ITuple的运行时类型,则它还支持类似于元组的模式语法(没有提供类型)。
positional_pattern
: type? '(' subpatterns? ')' property_subpattern? simple_designation?
;
subpatterns
: subpattern (',' subpattern)*
;
subpattern
: pattern
| subpattern_name ':' pattern
;
subpattern_name
: identifier
| subpattern_name '.' identifier
;
给定输入值与模式 类型(子模式)的匹配项后, 可以通过搜索类型 中搜索可访问声明 Deconstruct 并选择其中一个方法,并使用与解构声明相同的规则来选择一个方法。
如果positional_pattern省略类型、没有标识符的单个子模式、没有property_subpattern且没有simple_designation,则错误。 这在括号和positional_pattern的constant_pattern之间消除歧义。
为了提取要与列表中的模式匹配的值,
- 如果省略 类型 并且输入表达式的类型为元组类型,则子模式的数目应与元组的基数相同。 每个元组元素都与相应的 子模式匹配,如果所有这些元素都成功,匹配将成功。 如果任何 子模式 都有 标识符,则应将元组元素命名为元组类型中相应位置的元组元素。
- 否则,如果适合
Deconstruct作为 类型的成员存在,则如果输入值的类型与 类型不兼容,则为编译时错误。 在运行时,将针对 类型测试输入值。 如果此作失败,则位置模式匹配失败。 如果成功,则输入值将转换为此类型,并使用Deconstruct新的编译器生成的变量调用,以接收输出参数。 收到的每个值都与相应的 子模式匹配,如果所有这些值都成功,则匹配成功。 如果任一 子模式 具有 标识符,则应将参数命名为相应的位置Deconstruct。 - 否则,如果省略 类型 ,并且输入值为类型
object或某种类型,可通过隐式引用转换转换为System.ITuple某种类型,并且子模式之间不会显示 标识符 ,则匹配将使用System.ITuple。 - 否则,模式是编译时错误。
未指定运行时匹配子模式的顺序,并且失败的匹配可能不会尝试匹配所有子模式。
示例:此处,我们将解构表达式结果,并将结果值与相应的嵌套模式匹配:
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); }end 示例
示例:元组元素和析构参数的名称可用于位置模式,如下所示:
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); }生成的输出为
Sum of [10 20 30] is 60end 示例
11.2.6 属性模式
property_pattern检查输入值是否不null,并且以递归方式匹配通过使用可访问属性或字段提取的值。
property_pattern
: type? property_subpattern simple_designation?
;
property_subpattern
: '{' '}'
| '{' subpatterns ','? '}'
;
如果property_pattern的任何子模式不包含subpattern_name,则为错误。
如果 类型 为可以为 null 的值类型(§8.3.12)或可为空引用类型(§8.9.3),则为编译时错误。
注意:null 检查模式超出了一个普通的属性模式。 若要检查字符串
s是否为非 null,可以编写以下任一形式:#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 {}) ...尾注
给定表达式 e 与模式类型{子模式}的匹配,如果表达式 e与类型指定的 T 类型不兼容,则为编译时错误。 如果该类型不存在,则假定该类型为 e 的静态类型。 每个subpattern_name在其子模式的左侧出现,应指定一个可访问的可读属性或 T 字段。如果property_pattern simple_designation存在,则声明类型为 T 的模式变量。
在运行时,表达式针对 T 进行测试。如果此作失败,则属性模式匹配失败,结果为 false。 如果成功,则读取每个 property_subpattern 字段或属性,并且其值与相应的模式匹配。 整个匹配 false 的结果仅当其中任何一项的结果为 false时。 未指定子模式的匹配顺序,失败的匹配可能无法在运行时测试所有子模式。 如果匹配成功,并且property_pattern的simple_designation为single_variable_designation,则会为声明的变量分配匹配的值。
property_pattern可用于与匿名类型进行模式匹配。
subpattern_name可以引用嵌套成员。 在这种情况下,每个名称查找的接收方都是上一个成员 T₀ 的类型,从property_pattern的输入类型开始。 如果 T 是可以为 null 的类型, 则 T₀ 是其基础类型,否则 T₀ 等于 T。例如,窗体 { Prop1.Prop2: pattern } 的模式与 { Prop1: { Prop2: pattern } }..
注意:当 T 是可以为 null 的值类型或引用类型时,这将包括 null 检查。 此 null 检查意味着可用的嵌套属性将是 T₀ 的属性,而不是 T 的属性。允许重复成员路径时,模式匹配的编译可以利用模式的常见部分。 尾注
示例:
var o = ...; if (o is string { Length: 5 } s) ...end 示例
示例:运行时类型检查和变量声明可以添加到属性模式,如下所示:
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."), };生成的输出为
Hello Hi! 12345 abcend 示例
11.2.7 放弃模式
每个表达式都与放弃模式匹配,这会导致放弃表达式的值。
discard_pattern
: '_'
;
在表单relational_expression模式的is中或作为switch_label模式的模式使用放弃模式是编译时错误。
注意:在这些情况下,若要匹配任何表达式,请使用带放弃
var _。 尾注
示例:
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, };生成的输出为
5.0 0.0 0.0此处,使用放弃模式来处理
null任何没有相应枚举成员的DayOfWeek整数值。 这可以保证switch表达式处理所有可能的输入值。 end 示例
11.2.8 类型模式
type_pattern用于测试模式输入值(§11.1)是否具有给定类型。
type_pattern
: type
;
类型模式命名类型T适用于与E模式兼容的T 每种类型E(§11.2.2)。
值的运行时类型使用 is-type 运算符中指定的相同规则(§12.15.12.1)针对类型进行测试。 如果测试成功,则模式与该值匹配。 如果类型为可以为 null 的类型 ,则为编译时错误。 此模式形式永远不会与值 null 匹配。
11.2.9 关系模式
relational_pattern用于根据常量值对模式输入值(§11.1)进行关系测试。
relational_pattern
: '<' relational_expression
| '<=' relational_expression
| '>' relational_expression
| '>=' relational_expression
;
relational_pattern中的relational_expression需要计算为常量值。
关系模式支持关系运算符、以及<支持具有相同类型的两个操作数的二元关系运算符的所有内置类型:<=、、>、>=、sbyte、byteshortushortintuintlongulongchar、float、 double和枚举。 decimalnintnuint
如果使用类型两个操作数定义合适的内置二进制关系运算符,或者存在从常量表达式类型到常量表达式类型的显式可为 null 或取消装箱转换,则relational_patternTT类型T。
如果表达式的计算结果 double.NaN为 null float.NaN常量,则为编译时错误。
当输入值的类型定义了合适的内置二进制关系运算符时,该运算符的计算将被视为关系模式的含义。 否则,输入值将使用显式可为 null 或取消装箱转换转换为常量表达式的类型。 如果不存在此类转换,则为编译时错误。 如果转换失败,则模式被视为不匹配。 如果转换成功,则模式匹配操作的结果是计算转换后的输入的e «op» v表达式e的结果,«op» 是关系运算符,并且v是常量表达式。
示例:
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", };生成的输出为
Too high Unknown Acceptableend 示例
11.2.10 逻辑模式
logical_pattern用于否定模式匹配的结果,或者使用联合()或解禁and(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、 and和 or 统称为 模式运算符。
如果被否定的模式不匹配, 则negated_pattern 匹配,反之亦然。
conjunctive_pattern需要两种模式才能匹配。
disjunctive_pattern需要任一模式才能匹配。 与其&&语言运算符对应项||不同, andor也不是短路运算符。
这是模式变量在模式not运算符下or声明的编译时错误。
注意:由于模式变量既
notor不能也不能生成明确的赋值,所以在这些位置声明一个是错误的。 尾注
在conjunctive_pattern中,第二个模式的输入类型因第一个模式的类型缩小要求而and。 模式的P定义如下:
- 如果是
P类型模式,则 窄类型 是类型模式的类型。 - 否则,如果是
P声明模式,则 窄类型 是声明模式的类型。 - 否则,如果
P递归模式提供显式类型,则 窄类型 为该类型。 - 否则,如果
P通过positional_pattern(§11.2.5)中的规则ITuple进行匹配,则缩小的类型为类型System.ITuple。 - 否则,如果
P常量模式中常量不是 null 常量,而表达式没有常量表达式转换为输入类型,则窄类型是常量的类型。 - 否则,如果
P常量表达式没有常量表达式转换为输入类型的关系模式,则窄类型是常量的类型。 - 否则,如果
P为or模式, 则窄类型 是子模式的 窄类型的常见类型 (如果存在此类常见类型)。 为此,通用类型算法只考虑标识、装箱和隐式引用转换,并考虑一系列or模式的所有子模式(忽略括号模式)。 - 否则,如果
P为and模式,则 窄类型 为右模式的 窄类型 。 此外,左模式的 窄类型 是右模式的 输入类型 。 - 否则,缩小的类型
P为P“输入类型”。
注意:如语法所示,
not优先于and具有优先or顺序。 这可以通过括号显式指示或重写。 尾注
当模式出现在右侧is时,模式的范围由语法决定;因此,模式运算符andor和not模式内绑定比逻辑运算符&&更紧密,||并且!与模式外部绑定。
示例:
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", };生成的输出为
High Too low Acceptableend 示例
示例:
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}."), };生成的输出为
winter autumn springend 示例
示例:
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}");生成的输出为
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: Trueend 示例
11.3 模式子建议
在 switch 语句中,如果事例的模式被前面的未保护事例集(§13.8.3)子化,则为错误。 非正式地说,这意味着任何输入值都将与前面的案例之一匹配。 以下规则定义一组模式何时将给定模式子化:
如果满足以下任一条件,模式 P将匹配 常量 K :
- 该模式的运行时行为的规范是
P匹配K的。 -
P是类型T,K不是null,并且运行时类型K是T派生自T的类型或实现T的类型。 -
P是一个 具有 运算符 «op» 和常量vrelational_pattern,表达式K«op»v的计算结果为true。 -
P是一个negated_pattern,not P₁P₁不匹配K。 -
P是 一个conjunctive_pattern,P₁ and P₂两者P₁都将匹配K并P₂匹配K。 -
P是 一个disjunctive_pattern,P₁ or P₂要么P₁匹配K,要么P₂匹配K。 -
P是 一个discard_pattern。
如果满足以下任一条件,则一组模式Q会子化模式P:
-
P是一个常量模式,集中Q的任何模式都与转换P匹配 -
P是 var 模式,模式集Q对于模式输入值的类型(§11.4 -
P是具有类型的T声明模式,并且该类型Q(§11.4)的模式T集是详尽的。 -
P是一个类型T,并且该类型的Q模式集T的。 -
P是一个 具有 运算符 «op» 和常量值的vrelational_pattern,对于满足关系 «op»v的输入类型的每个值,集中Q的一些模式将匹配该值。 -
P是一个disjunctive_patternP₁ or P₂和一组模式Q子和P₁Q子项。P₂ -
P是一个conjunctive_patternP₁ and P₂,并且至少有一个保留Q:子或P₁Q子项。P₂ -
P是一个negated_patternnot P₁,Q并且对于仅考虑不匹配的值的输入类型P₁的。 -
P是一个discard_pattern,模式集Q对于模式输入值的类型是详尽的,并且模式输入值不是可以为 null 的类型,或者某些Q模式匹配。null - 某些模式
Q是一种 disjunctive_pattern,Q₁ or Q₂并将该模式替换为Q₁该Q模式将产生一个子集P,或者将其替换为Q₂将生成一个子集P。 - 某些模式
Q是negated_pattern,not Q₁P与任何匹配的值Q₁不匹配。
11.4 模式详尽
非正式情况下,如果对于该类型(非 null)的每个可能值,则一组模式对于类型而言都是详尽的,则集中的某些模式适用。 以下规则定义类型一组模式 何时详尽 :
如果满足以下任一条件,则一组模式Q的:
-
T是整数或枚举类型,或其中一个的可为 null 版本,对于'不可为 null 的基础类型的每个可能值T,某些Q模式将匹配该值;或 - 某些模式
Q是 var 模式;或 - 某些模式
Q是类型的D,并且存在标识转换、隐式引用转换或从T到D的装箱转换;或 - 某些模式
Q是类型D,并且存在标识转换、隐式引用转换或从T中转换到D的装箱转换; 或 - 某些模式
Q是 discard_pattern;或 - 这些模式
Q包括 relational_patterns 和 constant_pattern的组合,其范围共同涵盖不可为 null 的基础类型的每个可能值T。 对于float和double类型,这包括System.Double.NaN或System.Single.NaN分别,因为NaN与任何关系模式不匹配;或 - 某些模式
Q是一种disjunctive_patternP₁ or P₂,并将该模式替换为这P₁两种模式,并P₂Q生成一个详尽的T集合;或 - 某些模式是一种
Q,这些模式not P₁Q与未匹配的值一P₁起涵盖每个可能的值T。 当匹配可能的值时not P₁P₁本身T就详尽无遗; 或 - 某些模式
Q是一个conjunctive_patternP₁ and P₂,并且仅包含的集是P₁详尽的T,并且仅包含的集是P₂详尽的T。
注意:当类型模式包含可为 null 的类型时,该模式可能详尽无遗,但仍会生成警告,因为类型模式与值不匹配
null。 尾注
注意:对于浮点类型,模式
< 0>= 0的组合并不详尽,因为两种关系模式都不匹配NaN。 正确的详尽集是< 0,>= 0和double.NaN(或float.NaN)。 尾注
示例:
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; } }end 示例