c#笔记-模式匹配

模式匹配

模式匹配可以判断一个值的类型和内容。
可以判断嵌套的属性,但只能和常量进行比较。

模式匹配使用is表达式,或是在switch选择,和switch表达式的分支块中启用。

  • 模式匹配使用专有的关键字或运算符,这意味着不接收自定义的运算符和类型转换。
  • 模式匹配大都会返回一个bool值。
  • 模式匹配只对判断值进行一次取值,如果判断条件覆盖所有情况,编译器会发出提示,但不会编译为常量。

值判断

类型

使用模式匹配检查值的类型,只会判断他的类型是否和目标类型有继承链上的关系。
例如,int虽然能转换为float,但和float没有继承关系。模式匹配不会认为intfloat

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和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种,按照优先级分别为notandor
如果要修改优先级,需要使用括号。

int i3 = "Hello" switch
{
    
    
	"apple" => 6,//是apple
	"red" or "blue" => 9,//red或blue都行
	not "one" and "tow" => 12,//不是one,并且是tow
	"c#" or not "java" => 15,//是c#,或者是任何不是java的东西
	not ("root" or "Android" or "Ios") => 21//既不是root,也不是Android,也不是Ios
};

可空值类型只能用在单独的类型判断中,
使用逻辑模式判断类型,必须独立使用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,//使用弃元放弃对元素判断,只要求恰好包含5个元素
	[0, _, 20, _] => 4,//要求有4个元素,且第一个和第三个是0和20.
	[string {
    
     Length: 0 }] => 0,//要求有1个元素,且对这个元素进行模式匹配
	[2, .., 5] => 2,//要求至少有2个元素,首尾分别是2和5。中间可以有任意的元素
	[] => 3,//要求没有元素
	null => 1//是null
};

解构

当一个值是元组,或者能像元组一样解构时,可以在模式匹配中对他的解构值进行匹配。

(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);
}

猜你喜欢

转载自blog.csdn.net/zms9110750/article/details/130538762
今日推荐