1. 前言
你應該已經會寫這種 code:
switch (color)
{
case "red":
Console.WriteLine("停!");
break;
case "yellow":
Console.WriteLine("等一下...");
break;
case "green":
Console.WriteLine("可以走囉!");
break;
default:
Console.WriteLine("這是什麼顏色啊?");
break;
}
但如果我們想根據輸入參數給變數不同值,比如從 function 回傳一個根據數字決定的字串呢?在 switch-表達式 出現之前,只能寫成這樣:
string meaning;
switch (number)
{
case 42:
meaning = "生命、宇宙以及一切的終極答案";
break;
case 7:
meaning = "幸運數字";
break;
default:
meaning = "普通數字";
break;
}
這樣寫對 21 世紀的語言來說有點不夠優雅對吧?我們都想直接回傳值,就像 functional language 那樣。
這時候 switch-表達式 就出現啦——這是 C# 8.0 以後最美(也最新)的功能之一。
2. switch-表達式:讓人想抱一下的語法
來比較一下:operator 跟 expression
傳統的 switch 是 statement(「語句」),而 switch-表達式 是 expression,也就是它會算出一個值,可以直接 assign 給變數或 return 出去。
switch-表達式的結構:
var result = value switch
{
pattern1 => expression1,
pattern2 => expression2,
_ => defaultExpression // 「底線」就是「其他情況」
};
舉個例:
int number = 42;
string meaning = number switch
{
42 => "生命、宇宙以及一切的終極答案",
7 => "幸運數字",
_ => "普通數字"
};
Console.WriteLine(meaning); // => 生命、宇宙以及一切的終極答案
超簡潔、超好讀,沒有一堆 code,也不用 break;。
注意: 底線 _ 就是「抓所有剩下的 case」,跟 default 一樣意思。
3. switch-表達式 跟 pattern 怎麼配合
這裡才真的好玩。在 switch-表達式 裡不只可以用普通值,還能用 pattern:像是範圍、型別、物件屬性、deconstruct(把物件拆成幾個部分),甚至還有 combinatorial patterns(and、or、not)。
switch-表達式裡的 pattern 範例
常數 pattern
這就是我們上面做的:跟 42、7 比較等等。
範圍跟比較
int age = 17;
string category = age switch
{
< 18 => "未成年",
>= 18 and <= 65 => "成年人",
> 65 => "長者",
_ => "未知年齡分類"
};
Console.WriteLine(category);
順帶一提,可以一起用多個條件!C# 越來越 expressive 了。
型別 pattern(Type Patterns)
假設我們有個 object,可能是不同型別(像 object value;)。我們可以這樣處理不同型別:
object value = 3.14;
string description = value switch
{
int i => $"整數:{i}",
double d => $"小數:{d:F2}",
string s => $"這是字串:'{s}'",
null => "null!",
_ => "其他東西"
};
Console.WriteLine(description); // => 小數:3.14
關聯 pattern(Property Patterns 跟 Positional Patterns)
從 C# 8 開始,我們可以直接在 switch-表達式 裡檢查屬性值。
物件範例
public class User
{
public string Name { get; set; }
public int Age { get; set; }
}
User user = new User { Name = "安娜", Age = 17 };
string welcome = user switch
{
{ Age: < 18 } => $"哈囉,{user.Name}!你是青少年。",
{ Age: >= 18 and <= 65 } => $"嗨,{user.Name}!成年生活很棒吧。",
{ Age: > 65 } => $"歡迎,{user.Name}!永遠歡迎你。",
_ => "未知年齡"
};
Console.WriteLine(welcome);
這裡大括號裡的 { Age: < 18 } 就是 property pattern,也就是只檢查物件的某個屬性。
4. C# 11-14 的新 pattern
C# 越來越簡潔又靈活。最近加了 combinatorial patterns:and、or、not,還有更強的 positional patterns。來看看怎麼用。
邏輯 pattern:and、or、not
你可以像數理邏輯一樣組合條件!
int temperature = 25;
string result = temperature switch
{
< 0 => "超冷!",
>= 0 and < 20 => "有點涼",
>= 20 and < 30 => "很舒服",
>= 30 or <= -30 => "極端!",
_ => "奇怪的溫度"
};
如果想排除某些 case,也可以:
int score = 80;
string grade = score switch
{
>= 90 => "優秀",
>= 60 and not >= 90 => "不錯",
_ => "不好"
};
Deconstruct(Positional Patterns)
如果你有 struct 或 record 支援 deconstruct,C# 讓你直接在 switch-表達式 裡把物件拆開:
public record Point(int X, int Y);
Point p = new Point(10, 20);
string desc = p switch
{
(0, 0) => "原點",
(var x, 0) => $"在 X 軸上, X={x}",
(0, var y) => $"在 Y 軸上, Y={y}",
(var x, var y) when x == y => $"在對角線上: {x}",
_ => $"在點 ({p.X}, {p.Y})"
};
Console.WriteLine(desc); // => 在點 (10, 20)
5. 什麼時候該用 switch-表達式
在現代 C# 裡,switch-表達式 不只是炫技,而是真的能讓你少寫一堆廢話,讓 code 更精簡、更好測試、更好維護。這在寫 parser、command handler、商業邏輯、規則設定時超有感——只要你要根據複雜條件分支,不管是值、型別、範圍、屬性、組合條件都超適合。
面試時
- 你會怎麼處理用戶的不同回應?
- 怎麼讓 function 根據型別和值回傳不同結果?
- 怎麼輕鬆加新規則,不用一堆 if-else?
直接秀 switch-表達式 加 pattern!馬上展現你會用新語法、寫 code 很潮。
表格:switch operator 跟 switch-表達式 比較
| 特性 | switch statement | switch expression |
|---|---|---|
| 型別 | 語句 (statement) | 表達式 (expression) |
| 要不要 break | 一定要 | 不用 |
| 能不能回傳值 | 只能透過變數 | 可以直接回傳值 |
| 能不能用 pattern | 部分可以 | 完全可以(型別、屬性等) |
| 陷阱 | 可能忘記 break | 每個分支都要回傳值 |
6. 常見錯誤跟小陷阱
- 新手常常搞不清楚 switch operator(「statement」)跟 switch-表達式(「expression」)的差別。像是忘了 switch-表達式 不用 break;,而且每個分支都一定要回傳值。
- 如果忘了寫 _ 分支,compiler 會提醒你:「那如果都不符合怎麼辦?」
- switch-表達式 不能用 goto(這樣其實比較好 XD)。
- 如果有重複的條件(像兩個一樣的 pattern),compiler 也不會讓你過。
- 要注意 switch-表達式 回傳值的型別,要跟你 assign 的變數型別相容。
GO TO FULL VERSION