CodeGym /課程 /C# SELF /switch-表達式 和新型 patte...

switch-表達式 和新型 pattern

C# SELF
等級 10 , 課堂 5
開放

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
傳統的 switchstatement(「語句」),而 switch-表達式expression,也就是它會算出一個值,可以直接 assign 給變數或 return 出去。

switch-表達式的結構:


var result = value switch
{
    pattern1 => expression1,
    pattern2 => expression2,
    _       => defaultExpression // 「底線」就是「其他情況」
};
switch-表達式 的語法

舉個例:

int number = 42;
string meaning = number switch
{
    42 => "生命、宇宙以及一切的終極答案",
    7  => "幸運數字",
    _  => "普通數字"
};
Console.WriteLine(meaning); // => 生命、宇宙以及一切的終極答案

超簡潔、超好讀,沒有一堆 code,也不用 break;

注意: 底線 _ 就是「抓所有剩下的 case」,跟 default 一樣意思。

3. switch-表達式 跟 pattern 怎麼配合

這裡才真的好玩。在 switch-表達式 裡不只可以用普通值,還能用 pattern:像是範圍、型別、物件屬性、deconstruct(把物件拆成幾個部分),甚至還有 combinatorial patternsandornot)。

switch-表達式裡的 pattern 範例

常數 pattern
這就是我們上面做的:跟 427 比較等等。

範圍跟比較

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 patternsandornot,還有更強的 positional patterns。來看看怎麼用。

邏輯 pattern:andornot

你可以像數理邏輯一樣組合條件!

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 的變數型別相容。
1
問卷/小測驗
常數跟關鍵字 var,等級 10,課堂 5
未開放
常數跟關鍵字 var
常數、結構、enum 跟 switch
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION