在C#的SwitchExpression下使用模式比對(Pattern Matching)
C# 9.0再度增強了模式比對(Pattern matching enhancements)的表述能力後,再佐以各式的Recursive Pattern Matching,讓整個Switch運算式(Switch Expressions)撰寫起來已經接近外星語言等級了,實在很擔心C#再繼續往這種極簡的函式語言(Functional Programming;FP)靠攏,若整個官網若都充斥著此類語法範例,對於初學者而言這個語言大概會被放棄掉吧...
這邊透過Switch運算式:SwitchExpression的結構(傳統寫法叫做Switch語句:SwitchStatement),把模式比對的寫法綜合表述一下,供給有需要的人員參考。
SwitchExpression於C# 9.0增強範例
不囉嗦,直接上程式碼
public class Program
{
public static void Main()
{
Show(Check( 0, "TheBOYSayWANNADrink"));
Show(Check( 1, "TheGirlSayWannaEat"));
Show(Check( 2, "OthersString"));
Show(Check( 3, -100));
Show(Check( 4, 123));
Show(Check( 5, 199));
Show(Check( 6, 201));
Show(Check( 7, ("John", 17)));
Show(Check( 8, ("John", 18)));
Show(Check( 9, ("John", 19)));
Show(Check(10, new Human1("John", 17)));
Show(Check(11, new Human1("John", 18)));
Show(Check(12, new Human1("John", 19)));
Show(Check(13, new Human2() { cName="John", iAge = 17}));
Show(Check(14, new Human2() { cName="John", iAge = 18}));
Show(Check(15, new Human2() { cName="John", iAge = 19}));
Show(Check(16, true));
}
public static string Check(int iIndex, System.Object oTemp) => oTemp switch
{ //string
string x when x.Equals("TheBoySayWannaDrink", System.StringComparison.CurrentCultureIgnoreCase) => $"{iIndex}. 字串A:傳入值為 / {x}",
"TheGirlSayWannaEat" => $"{iIndex}. 字串B",
string => $"{iIndex}. 只知道是字串",
//int
int x and < 0 => $"{iIndex}. 整數A:傳入值為 / {x}",
123 => $"{iIndex}. 整數B:",
int and > 0 and ( >= 100 and <= 200) => $"{iIndex}. 整數C",
int => $"{iIndex}. 只知道是整數",
//VauleTuple
System.ValueTuple<string, int> x when x == ("John", 17) => $"{iIndex}. ValueTupleA:傳入值為 / {x.Item1}",
("John", 18) => $"{iIndex}. ValueTupleB",
(_, _) => $"{iIndex}. 只知道是ValueTuple",
//ClassObject-1
Human1 { cName: "John", iAge: 17 } x => $"{iIndex}. 物件A:傳入值為 / {x.cName}",
Human1("John", 18) => $"{iIndex}. 物件A",
Human1 x => $"{iIndex}. 只知道是 / {x.GetType()}",
//ClassObject-2
Human2 { cName: "John", iAge: 17 } x => $"{iIndex}. 物件B:傳入值為 / {x.cName}",
Human2 { cName: "John", iAge: 18 } => $"{iIndex}. 物件B",
Human2 x => $"{iIndex}. 只知道是 / {x.GetType()}",
//default
_ => $"{iIndex}. 無法識別物件"
};
public static void Show(string cTemp) => Console.WriteLine(cTemp);
public record Human1(string cName, int iAge);
public class Human2
{
public string cName;
public int iAge;
}
}
輸出結果如下:
0. 字串A:傳入值為 / TheBOYSayWANNADrink
1. 字串B
2. 只知道是字串
3. 整數A:傳入值為 / -100
4. 整數B:
5. 整數C
6. 只知道是整數
7. ValueTupleA:傳入值為 / John
8. ValueTupleB
9. 只知道是ValueTuple
10. 物件A:傳入值為 / John
11. 物件A
12. 只知道是 / Program+Human1
13. 物件B:傳入值為 / John
14. 物件B
15. 只知道是 / Program+Human2
16. 無法識別物件
補充說明
- 程式碼中的整數那邊的判斷邏輯有點問題是我故意寫的(大於等於100肯定大於零),因為我只是想要表示可以用and or等語法。
- SwitchExpression在編譯時期會幫你檢測條件順序邏輯並給予警告,例如把數值判斷「123描述判斷」這行直接與下一行判斷交換,編譯器會直接告訴你錯誤(因為上面行號的邏輯已經包含了「123描述判斷」這行的邏輯),是一個非常有趣的行為。
- Record類別在PatternMatching時期可以用回類似「後宣告」而非「建構式宣告」的寫法,令人激賞。
相關連結
- 在C#的SwitchExpression下使用模式比對(Pattern Matching)
- 利用SwitchExpression來進行switch流程程式碼判斷的優化
- 利用SwitchExpression取代if-else,並閃避逐行判斷的寫法
- 利用C#的switch case when語法來忽略字串大小寫
- C#的IS與AS運算子之撰寫方法
- C#的NULL運算演化:?.、??、??=、以及模式比對增強功能
- 遞迴模式比對
- C# 9.0 中的新增功能