從C#7開始支持的 模式匹配 語法(糖,挺甜),可非常靈活的對(duì)數(shù)據(jù)進(jìn)行條件匹配和提取,經(jīng)過多個(gè)版本的完善,已經(jīng)非常強(qiáng)大了。
從
C#7
開始支持的
模式匹配
語法(糖,挺甜),可非常靈活的對(duì)數(shù)據(jù)進(jìn)行條件匹配和提取,經(jīng)過多個(gè)版本的完善,已經(jīng)非常強(qiáng)大了。
C# 支持多種模式,包括聲明、類型、常量、關(guān)系、屬性、列表、var 和棄元等,在
is
、
switch
語句、
switch
表達(dá)式中使用,還可以使用布爾邏輯關(guān)鍵字
and
、
or
和
not
組合多個(gè)模式,極大的簡化了代碼編寫,可讀性也還不錯(cuò)。
標(biāo)題 | 說明 | 示例/備注 |
---|---|---|
類型和聲明模式 | 如果類型兼容,則申明并賦值變量 |
if (age is int i)
|
常量模式 | 檢查表達(dá)式值是否等于、不等于(not)常量值 |
if(age is null || age is 0)
|
關(guān)系模式
><
|
使用關(guān)系運(yùn)算符
<
、
>
、
<=
或
>=
匹配
|
case 0 or <=6
|
邏輯模式 |
用
not
>
and
>
or
連接多個(gè)模式表達(dá)式
|
case < 12 and ( >6 or 6)
|
屬性模式
{:}
|
對(duì)實(shí)例的屬性、字段進(jìn)行模式匹配:
{屬性/字段:匹配模式}
|
if (b is { Year: < 2000, Month: 1 or 11 })
|
位置模式(解構(gòu)) |
基于解構(gòu)賦值進(jìn)行模式匹配:
(解構(gòu)參數(shù))
|
if(point is (_,>0,>0))
|
var 模式 |
用
var
申明(捕獲)任意局部變量
|
if(point is var p && p.X>0)
|
棄元模式_ |
棄元模式
_
來匹配任何(其他)表達(dá)式
|
表示不要的 |
列表模式[] |
對(duì)數(shù)組(列表)進(jìn)行匹配,在中括號(hào)
[]
中匹配列表中的項(xiàng)
|
if(numbers is [_, 2, 3, ..])
|
? 模式匹配基本都是語法糖,味道都不錯(cuò)!C#在編譯時(shí)會(huì)輸出原本的基礎(chǔ)代碼,可通過 https://sharplab.io/ 在線查看編譯后的代碼。
檢查類型是否匹配,同時(shí)申明變量,如果類型兼容則申明并賦值變量,該變量在后面代碼作用域中有效。
object age = "123";
if (age is int i) //類型匹配+申明變量i
{
Console.WriteLine($"age1 = {i}");
}
switch (age)
{
case string: //類型匹配
Console.WriteLine($"type is string");
break;
case int iage: //類型匹配+申明變量iage
Console.WriteLine($"age2 = {iage}");
break;
}
//上面is語句編譯后的代碼效果:
if (obj is int)
{
int value = (int)obj;
}
檢查表達(dá)式值是否等于、不等于(
not
)常量值,常量值包括字面量常量,也包括
const
常量值。傳統(tǒng)的
Switch
語句就是常量模式匹配。
object age = null;
if (age is not null && age is 100) //age is 100 等同于 age is int && (int)age==100
{
Console.WriteLine($"age1 = {age}");
}
var type = age switch{
1 or 2 or 3=>"嬰兒",
4 => "幼兒",
null or not 5 => "unknow",
_=>"",
};
><
用關(guān)系運(yùn)算符來匹配表達(dá)式,就是對(duì)常量數(shù)值進(jìn)行大小比較運(yùn)算,使用關(guān)系運(yùn)算符
<
、
>
、
<=
或
>=
,多個(gè)表達(dá)式可用
and
、
or
連接,當(dāng)然也支持括號(hào)。
object age = 6;
if (age is int n and >= 6)
{
Console.WriteLine("666");
}
switch (age)
{
case 0 or <=6:
Console.WriteLine("幼兒");
break;
case < 12 and ( >6 or 6):
Console.WriteLine("青少年");
break;
}
not
/
and
/
or
用
not
、
and
和
or
模式連結(jié)符來創(chuàng)建邏輯模式,連接多個(gè)模式表達(dá)式。
not
>
and
>
or
。
(括號(hào))
顯示控制優(yōu)先順序,可讀性更好。
object age = 6;
if (age is int n and (not 6 or >5) )
{
Console.WriteLine("666");
}
{:}
對(duì)實(shí)例的屬性、字段進(jìn)行模式匹配,可以嵌套其他模式匹配,非常的強(qiáng)大,屬性匹配用大括號(hào)來包裝
{屬性/字段:匹配模式}
。
true
時(shí),最終才會(huì)匹配成功。
DateTime birthday = new DateTime(1999, 11, 12);
if (birthday is { Year: < 2000, Month: 1 or 11 })
{
Console.WriteLine("年齡、星座不合適");
}
//嵌套使用
public record Point(int X, int Y);
public record Segment(Point Start, Point End);
static bool IsAnyEndOnXAxis(Segment segment) =>
segment is { Start: { Y: 0 } } or { End: { Y: 0 } };
static bool IsAnyEndOnXAxis(Segment segment) =>
segment is { Start.Y: 0 } or { End.Y: 0 };
基于解構(gòu)賦值進(jìn)行模式匹配:
Tuple
、
record
和
DictionaryEntry
是內(nèi)置支持解構(gòu)的,關(guān)于解構(gòu)賦值可參考相關(guān)內(nèi)容。
()
報(bào)裝,這也是
解構(gòu)(Deconstruct)
的語法形式。
void Main()
{
Point point = new Point("sam", 12, 13);
var len = point switch
{
//類型匹配、屬性模式、位置模式:Name屬性必須為string,且長度為0,X、Y值為0
(string { Length: <= 0 }, 0, 0) => 0,
(_, > 0, 0) => point.X, //X值大于0,Y值為0
(_, 0, > 0) => point.Y, //Y值大于0,X值為0
(_, 10 or > 10, 10 or > 10) p => p.X * p.Y,
_ => 0,
};
}
public record Point(string Name, int X, int Y);
用
var
申明(捕獲)任意局部變量,把表達(dá)式的結(jié)果分配給
var
臨時(shí)變量。算是類型模式的變種,將類型名替換成了
var
。
void Main()
{
Point point = new Point("sam", 12, 13);
if(point is var p && p.X>0 && p.Y>0){ //is var
Console.WriteLine("OK");
}
var len = point switch
{
var (_,x,y) when x>0 && y>0 => true,// var
};
}
public record Point(string Name, int X, int Y);
棄元模式
(Discard Pattern),字面理解就是被遺棄、沒人要的。可以將棄元模式看做是一個(gè)占位符,表示一個(gè)沒人用的變量,可匹配任意類型,用來
簡化代碼
。語法是用下劃線“
_
”表示。
常用場景 :
Switch
中匹配任意其他模式,類似
default
的作用。
out
參數(shù)中占位,表示一個(gè)沒人用的
out
參數(shù)。
var tuple = new Tuple(3, 4);
var (x, _) = tuple; //1、只需要第一個(gè)參數(shù),其他就用“_”來占位
Console.WriteLine(x); //3
_= x switch
{
2 or <2 => "small",
int and <18=>"young",
_=>"other", //2、匹配其他模式,效果同default
};
int.TryParse("", out _); //3、不用的out變量,實(shí)際上是申明了變量的
async void Print(object arg)
{
_ = arg ?? throw new ArgumentException(); //4、接收無用的返回,效果同下
if (arg == null) throw new ArgumentException();
_ = Task.Run(()=>Console.WriteLine("task run")); //接收一個(gè)不用的返回
}
棄元模式
_
是一個(gè)提供給編譯器用的符號(hào),告訴編譯這個(gè)變量不用了,編譯器會(huì)根據(jù)情況進(jìn)行優(yōu)化處理。在對(duì)
out
參數(shù)使用時(shí),編譯器會(huì)自動(dòng)創(chuàng)建變量,如下代碼:
int.TryParse("",out _);
//實(shí)際編譯后的代碼如下
int result;
int.TryParse("", out result);
?需要注意的是 下劃線
_
是并不是一個(gè)關(guān)鍵字,也能當(dāng)做參數(shù)名來使用,不要混用。
C#11支持的,對(duì)數(shù)組(列表)進(jìn)行匹配,在中括號(hào)
[]
中匹配列表中的項(xiàng)。
_
。
void Main()
{
int[] numbers = { 1, 2, 3, 4 };
Console.WriteLine(numbers is [_, 2, 3, ..]); // True
Console.WriteLine(numbers is [0 or 1, <= 2, >= 3]); // False
}
上面的各種模式匹配主要就用在 is 運(yùn)算符 、 switch 語句 、 switch 表達(dá)式 中。
is 運(yùn)算符 本來主要是用來檢測類型兼容性的,加上模式匹配就能玩出各種花樣了,極大簡化了讓各種檢查類的代碼。
object value = 12;
if (value is int && value is not null) //is類型檢測+邏輯模式
{
Console.WriteLine(value);
}
if (value is int a && a > 6) //+申明模式
{
Console.WriteLine(a);
}
if (value is int age and > 10 and < 14) //關(guān)系模式
{
Console.WriteLine(age);
}
var user = new { Name = "sam", Age = 12 };
if (user is { Name: _, Age: > 10 }) //屬性模式
{
Console.WriteLine(user.Name);
}
int[] arr = new int[] { 1, 2, 3 };
if (arr is [> 0, ..]) //列表模式:第一個(gè)元素>0
{
Console.WriteLine(arr);
}
var dt = new Tuple("sam", 100);
if (dt is (_, > 60) d) //位置模式+申明模式(好像沒什么用)
{
Console.WriteLine(d.Item1);
}
switch..case 語句 是很多語言中都有的基本多條件分支語句,傳統(tǒng)的 case 只能用于匹配常量,多用于枚舉。
case
不能穿透,一個(gè)
case
執(zhí)行完后必須
break
結(jié)束,或者
return
返回(退出方法),可以多個(gè)
case
匹配執(zhí)行一組邏輯代碼。
case
就是常量模式,而現(xiàn)代的
case
可以結(jié)合上面多種模式使用,非常強(qiáng)大。
when
,自由附加更多條件。
int age = 22;
string sex = "Male";
switch (age)
{
case 1:
case 2:
Console.WriteLine("嬰兒");
break;
case <= 3:
Console.WriteLine("幼兒");
break;
case > 10 and < 16:
Console.WriteLine("青少年");
break;
case > 18 when sex == "Male":
Console.WriteLine("成年男性");
break;
case int:
break;
}
C#8
中
switch
有了新的語法 ——
switch 表達(dá)式
,可以看做是
switch..case
語句的一個(gè)變種,使用比較類似。
switch
表達(dá)式是一個(gè)賦值(輸出)語句。
=>
左側(cè)為模式(返回一個(gè)bool),如果模式匹配(true)則返回右側(cè)的值,最后一個(gè)棄元模式匹配其他情況,同
default
效果。
int type = 6;
var message = type switch
{
<= 1 => "success",
2 => "warning",
3 => "error",
> 3 and < 10 => "other error",
_ => "unkonwn error",
};
可以用
when
來進(jìn)行更多的判斷,
when
后面的表達(dá)式就很自由了,只要返回
boo
即可。
object type = 6;
var message = type switch
{
int i when i<6 => "ok",
string s when s=="null"=>"Null",
string s when !string.IsNullOrEmpty(s)=>"string value",
_=>"unknown value"
};
Console.WriteLine(message);
支持多個(gè)變量的組合模式:用括號(hào)
()
包含多個(gè)變量
string gender = "male";
int age = 10;
string type = (gender,age) switch{
("male",>18)=>"VIP",
(not "male",>26 and <35)=>"VVIP",
_=>"",
};
??版權(quán)申明 :版權(quán)所有@安木夕,本文內(nèi)容僅供學(xué)習(xí),歡迎指正、交流,轉(zhuǎn)載請(qǐng)注明出處! 原文編輯地址-語雀
機(jī)器學(xué)習(xí):神經(jīng)網(wǎng)絡(luò)構(gòu)建(下)
閱讀華為Mate品牌盛典:HarmonyOS NEXT加持下游戲性能得到充分釋放
閱讀實(shí)現(xiàn)對(duì)象集合與DataTable的相互轉(zhuǎn)換
閱讀鴻蒙NEXT元服務(wù):論如何免費(fèi)快速上架作品
閱讀算法與數(shù)據(jù)結(jié)構(gòu) 1 - 模擬
閱讀5. Spring Cloud OpenFeign 聲明式 WebService 客戶端的超詳細(xì)使用
閱讀Java代理模式:靜態(tài)代理和動(dòng)態(tài)代理的對(duì)比分析
閱讀Win11筆記本“自動(dòng)管理應(yīng)用的顏色”顯示規(guī)則
閱讀本站所有軟件,都由網(wǎng)友上傳,如有侵犯你的版權(quán),請(qǐng)發(fā)郵件[email protected]
湘ICP備2022002427號(hào)-10 湘公網(wǎng)安備:43070202000427號(hào)© 2013~2025 haote.com 好特網(wǎng)