类型模式

object obj = "hello";

// is + 模式
if (obj is string s)
{
    Console.WriteLine(s.Length);    // s 已经是 string 类型,可直接用
}

// 老写法(不推荐)
if (obj is string)
{
    var s = (string)obj;            // 多此一举
    Console.WriteLine(s.Length);
}

is X x 同时检查类型 + 声明变量

switch 表达式(C# 8+)

string description = obj switch
{
    int n => $"integer {n}",
    string s => $"string '{s}'",
    null => "null",
    _ => $"something else: {obj.GetType().Name}",
};

返回值、模式紧凑、穷举性检查(漏分支编译器告警)。

属性模式

record class Person(string Name, int Age, string City);

string Classify(Person p) => p switch
{
    { Age: < 18 } => "未成年",
    { Age: >= 65 } => "老年",
    { Age: >= 18 and < 65, City: "Beijing" } => "北漂",
    { Age: >= 18 and < 65 } => "中青年",
    _ => "未知",
};

{ Property: pattern } 检查属性值匹配。嵌套也行:

{ Address: { City: "Beijing" } }
// 或简写(C# 10+)
{ Address.City: "Beijing" }

关系模式(C# 9+)

x switch
{
    < 0 => "负",
    0 => "零",
    > 0 and < 10 => "小正数",
    >= 10 and <= 100 => "中等",
    > 100 => "大",
}

< > <= >= == 直接用作模式。

逻辑模式

n switch
{
    1 or 2 or 3 => "小",
    not 0 => "非零",
    > 0 and < 10 => "1-9",
}

and / or / not 组合。

列表模式(C# 11+)

int[] arr = { 1, 2, 3 };

string desc = arr switch
{
    [] => "空",
    [_] => "一个元素",
    [1, ..] => "1 开头",
    [.., 3] => "3 结尾",
    [1, _, 3] => "1 ? 3",
    [var first, ..] => $"开头是 {first}",
};

.. 是"任意个"占位;var x 捕获元素。

解构模式

record class Point(int X, int Y);

string Quadrant(Point p) => p switch
{
    (0, 0) => "原点",
    (> 0, > 0) => "第一象限",
    (< 0, > 0) => "第二象限",
    var (x, y) when x == y => $"对角线 ({x},{y})",
    _ => "其他",
};

(x, y) 解构(record / tuple / 自定义 Deconstruct)。

var 模式 + when

x switch
{
    var n when n > 0 && n < 10 => $"小正数 {n}",
    var n => $"其他 {n}",
}

var n 永远匹配 + 捕获,配 when 加额外条件。

实战:状态机

record class Loading;
record class Loaded(string Data);
record class Failed(string Error);

object state = ...;

string Display(object state) => state switch
{
    Loading => "加载中...",
    Loaded(string data) => $"数据: {data}",
    Failed(string err) => $"错误: {err}",
    _ => "未知",
};

配合 record 解构 + 类型模式——和 Rust / Scala 的代数数据类型很接近。

不要忘 _ 兜底

DayOfWeek day = DayOfWeek.Monday;
string msg = day switch
{
    DayOfWeek.Monday => "周一",
    DayOfWeek.Tuesday => "周二",
    // 编译警告:可能没匹配到 Wednesday-Sunday
};

穷举性检查——枚举漏分支编译器警告。要么列全所有分支,要么 _ => default;

switch 表达式 vs switch 语句

// 表达式:返回值
var msg = x switch { ... };

// 语句:执行代码块
switch (x)
{
    case 1:
        DoSomething();
        break;
    case 2 or 3:
        DoOther();
        break;
}

新代码优先表达式——简洁、强类型、强检查。语句版本只在分支需要多语句副作用时用。

模式匹配 vs if 链

// ❌ if-else 链
if (obj is int n) ...
else if (obj is string s) ...
else if (obj is null) ...
else ...

// ✅ switch 表达式
var result = obj switch
{
    int n => ...,
    string s => ...,
    null => ...,
    _ => ...,
};

3+ 分支用 switch;2 个用 if 也行。

→ 下一篇 可空引用类型