模式匹配
模式匹配可以判断一个值的类型和内容。
可以判断嵌套的属性,但只能和常量进行比较。
模式匹配使用is
表达式,或是在switch选择
,和switch表达式
的分支块中启用。
- 模式匹配使用专有的关键字或运算符,这意味着不接收自定义的运算符和类型转换。
- 模式匹配大都会返回一个bool值。
- 模式匹配只对判断值进行一次取值,如果判断条件覆盖所有情况,编译器会发出提示,但不会编译为常量。
值判断
类型
使用模式匹配检查值的类型,只会判断他的类型是否和目标类型有继承链上的关系。
例如,int
虽然能转换为float
,但和float
没有继承关系。模式匹配不会认为int
是float
object o1 = 1;
Console.WriteLine(o1 is int);
Console.WriteLine(o1 is float);
Console.WriteLine(o1 is double);
int i1 = 20;
Console.WriteLine(i1 is string);
关系
模式匹配可以判断值和常量的关系,例如相等,大于,小于。
不相等需要从逻辑模式进行判断。
int i2 = 20;
switch (i2)
{
case >= 30:
Console.WriteLine("超过30");
break;
case < 10:
Console.WriteLine("没有10");
break;
case 20:
Console.WriteLine("是20");
break;
default:
Console.WriteLine("都不对");
break;
}
逻辑
逻辑模式有3种,按照优先级分别为not
的非
,and
的且
,or
的或
。
如果要修改优先级,需要使用括号。
int i3 = "Hello" switch
{
"apple" => 6,
"red" or "blue" => 9,
not "one" and "tow" => 12,
"c#" or not "java" => 15,
not ("root" or "Android" or "Ios") => 21
};
可空值类型只能用在单独的类型判断中,
使用逻辑模式判断类型,必须独立使用null
和基础值类型。
object? o2 = null;
_ = o2 is float?;
_ = o2 is float or int or null;
内容判断
属性
使用使用大括号展开,可以对他的属性进行模式匹配的判断。
bool b1 = "Hello" is { Length: > 4 };
Console.WriteLine(b1);
进行内容判断时,模式匹配首先会判断他是否为null。
也就是说一个空的内容判断相当于进行一个非空判断。
string? s1 = null;
_ = s1 is { };
_ = s1 is not null;
内容判断可以联合类型判断进行。
对不同的类型进行不同的内容判断。
object o = 1..^1;
switch (o)
{
case Range { Start: { Value: 0 }, End.IsFromEnd: false }:
break;
case int and > 2:
break;
case string { Length: 0 }:
break;
default:
break;
}
列表
对于数组,可以使用列表模式,检查元素数量,同样会先检查是否非空。
是用_
表示弃元,不进行判断只占位。也可以对每个元素单独进行模式匹配。
..
占位表示中间任意数量的元素(包括没有)。这样能表示前x个和对后x个元素匹配。
object[] arr1 = new object[4];
_ = arr1 switch
{
[_, _, _, _, _] => 5,
[0, _, 20, _] => 4,
[string { Length: 0 }] => 0,
[2, .., 5] => 2,
[] => 3,
null => 1
};
解构
当一个值是元组,或者能像元组一样解构时,可以在模式匹配中对他的解构值进行匹配。
(object, object) tup1 = ("小明", 18);
_ = tup1 is (int, string { Length: < 3 });
也不需要是元组变量。可以在switch对多值进行判断时临时打包一个元组。
int hp = 100;
int maxHp = 200;
switch ((hp, maxHp))
{
case ( > 100, > 100) when hp < maxHp / 1:
case (_, > 300 and < 500):
default:
break;
}
声明变量
类型
在带有类型的模式判断时,可以同时声明一个变量(只能声明不能覆盖)。
当模式完全匹配时,将会把判断值进行类型转换后赋值给它。
object o3 = 12;
if (o3 is int i4)
{
Console.WriteLine(i4 * i4);
}
else if (o3 is string s3)
{
Console.WriteLine(s3.Length);
}
只有带有流程控制语句中才能保证这些变量有初始值。
不能在一个模式里包含多个类型判断(使用or
)时进行声明。
var
仅当需要声明的时候,var
才能作为类型作为判断。
(int x, int y) point = (8, 4);
var p = point switch
{
(var x, var y) when x > y => 1,
(var x, var y) when x < y => -1,
(_, _) => 0
};
范围
在对数组进行列表的模式匹配时,可以对其中的范围模式进行变量声明。
int[] arr2 = { 3, 4, 5, 6, 7 };
if (arr2 is [_, 4, .. var arr3, _])
{
Console.WriteLine(arr3.Length);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)