<p>属性模式是C# 8+中用于is和switch中按对象公开属性值结构匹配的语法,只依赖public get访问器,支持嵌套、通配符和组合模式,但禁止方法调用。</p>

属性模式(property pattern)不是给属性加装饰,也不是在 get/set 里写逻辑——它是 C# 8+ 在 is 和 switch 中用来**按对象的属性值结构做匹配**的语法,和字段、构造函数无关,只和运行时对象的公开读取能力有关。
属性模式能匹配哪些东西
它只匹配具有 public get 访问器的属性(无论是否自动实现),不关心有没有 set、init 或后备字段。只要运行时能读出值,就能进模式分支。
- 自动属性:
public string Name { get; set; }✅ 可匹配 - 只读自动属性:
public int Id { get; } = 123;✅ 可匹配 - 带验证逻辑的属性:
public decimal Price { get => _price; set => _price = Math.Max(0, value); }✅ 可匹配(匹配的是get返回值) - private set 属性:
public string Tag { get; private set; }✅ 可匹配(get是 public) - 完全私有属性:
private string _internal { get; set; }❌ 不可匹配(无 public get)
写法:is + 属性模式 vs switch 表达式
两种写法语义一致,但 switch 表达式更紧凑,is 更适合单次判断。
常见错误是把属性名写成字符串或漏掉大括号。正确写法必须用 { PropertyName: valuePattern } 形式:
<pre class="brush:php;toolbar:false;">if (obj is Person { Name: "Alice", Age: >= 18 })
{
// 匹配成功:Name 等于 "Alice" 且 Age 大于等于 18
}
<p>var result = obj switch
{
Person { Name: var n, Age: 0 } => $"Newborn named {n}",
Person { Age: < 0 } => "Invalid age",
_ => "Not a Person or age out of range"
};</p>嵌套属性和通配符怎么用
属性模式支持深度嵌套,只要嵌套对象的属性也是 public get 就行。但要注意 null 引用——模式本身不做空检查,obj is Person { Address.City: "Beijing" } 在 <code>Address 为 null 时直接返回 false,不会抛异常。
- 用
_忽略某个属性:Person { Name: _, Age: 25 } - 用
var捕获值:Person { Name: var name, Age: var age } - 组合其他模式:
Person { Name: "Bob" or "Tom", Age: 18 or 19 } - 不能写方法调用:
Person { FullName.ToUpper(): "ALICE" }❌ 不合法(模式中不允许表达式求值)
和 required / init-only 属性的关系
required 修饰符只影响编译期初始化检查,对属性模式运行时行为零影响。哪怕一个 required string Name { get; init; } 在运行时是 null,它依然能参与匹配——只是匹配结果取决于实际值,不是声明意图。
容易被忽略的一点:如果类用了 record,它的 with 表达式和属性模式天然协同;但普通 class 若属性是 init 且未初始化,运行时值就是默认值(如 null 或 0),模式会如实匹配这个默认值,而不是报错或跳过。


















