Skip to content

Dart 模式匹配完整指南

模式类型

本页面是不同种类模式的参考文档。如需了解模式的工作原理、在 Dart 中的使用场景及常见用例,请访问主模式页面

模式优先级

优先级规则

  • 与运算符优先级类似,模式求值遵循优先级规则
  • 可使用带括号的模式优先计算低优先级模式

优先级从低到高:

  1. 逻辑或模式 (||)
  2. 逻辑与模式 (&&)
  3. 关系模式 (==, <, >, <=, >=)
  4. 后缀一元模式(类型转换、空值检查、空值断言)
  5. 其他主要模式(集合类型和对象模式)

注意:集合类型和对象模式因包含其他数据,会作为外部模式优先求值

逻辑或模式 (||)

dart
subpattern1 || subpattern2
  • 任一分支匹配即成功
  • 从左到右求值,匹配成功后不再求值后续分支

示例:

dart
var isPrimary = switch (color) {
  Color.red || Color.yellow || Color.blue => true,
  _ => false,
};
  • 子模式可绑定变量,但所有分支必须定义相同变量集合

逻辑与模式 (&&)

dart
subpattern1 && subpattern2
  • 两个子模式都匹配才成功
  • 左侧不匹配则不求值右侧

示例:

dart
switch ((1, 2)) {
  // 错误示例:两个子模式都尝试绑定 'b'
  case (var a, var b) && (var b, var c): // ...
}

关系模式

支持运算符:==, !=, <, >, <=, >=

示例(ASCII字符分类):

dart
String asciiCharType(int char) {
  const space = 32;
  const zero = 48;
  const nine = 57;

  return switch (char) {
    < space => 'control',
    == space => 'space',
    > space && < zero => 'punctuation',
    >= zero && <= nine => 'digit',
    _ => '',
  };
}

类型转换模式 (as)

dart
foo as String
  • 在解构过程中插入类型转换
  • 类型不匹配时抛出异常

示例:

dart
(num, Object) record = (1, 's');
var (i as int, s as String) = record;

空值检查模式 (?)

dart
subpattern?
  • 先检查非空,再应用内部模式
  • 允许绑定非空基类型变量

示例:

dart
String? maybeString = 'nullable with base type String';
switch (maybeString) {
  case var s?: // 's' 是非空 String
}

空值断言模式 (!)

dart
subpattern!
  • 先检查非空,再匹配值
  • 空值会抛出异常

示例:

dart
List<String?> row = ['user', null];
switch (row) {
  case ['user', var name!]: // 'name' 是非空 String
}

常量模式

匹配值等于常量的情况:

  • 数字字面量 (123, 45.56)
  • 布尔字面量 (true)
  • 字符串字面量 ('string')
  • 命名常量 (math.pi)
  • 常量构造函数 (const Point(0, 0))
  • 复杂表达式需用 const 包裹:case const (1 + 2):

示例:

dart
switch (number) {
  case 1: // 1 == number 时匹配
}

变量模式

dart
var bar, String str, final int _
  • 将匹配值绑定到新变量
  • 类型化变量模式需类型匹配

示例:

dart
switch ((1, 2)) {
  case (var a, var b): // a=1, b=2
}

标识符模式

行为取决于上下文:

  1. 声明上下文var (a, b) = (1, 2)
  2. 赋值上下文(a, b) = (3, 4)
  3. 匹配上下文:视为命名常量模式(除非名称为 _

通配符标识符 (_) 可匹配任意值并丢弃:

dart
case [_, var y, _]: print('中间元素是 $y');

集合模式

列表模式 ([subpattern1, subpattern2])

  • 匹配实现 List 的值
  • 按位置解构元素

示例:

dart
const a = 'a';
const b = 'b';
switch (obj) {
  case [a, b]: print('$a, $b');
}

Rest 元素 (...)

  • 匹配任意数量剩余元素
  • 可包含子模式收集未匹配元素

示例:

dart
// 基础用法
var [a, b, ..., c, d] = [1, 2, 3, 4, 5, 6, 7];
print('$a $b $c $d'); // 输出 "1 2 6 7"

// 收集未匹配元素
var [a, b, ...rest, c, d] = [1, 2, 3, 4, 5, 6, 7];
print('$rest'); // 输出 "[3, 4, 5]"

映射模式 ({"key": subpattern1, someConst: subpattern2})

  • 匹配实现 Map 的值
  • 不要求匹配整个映射
  • 访问不存在的键会抛出 StateError

示例:

dart
final {'foo': int? foo} = {};

记录模式 ((subpattern1, subpattern2)(x: subpattern1, y: subpattern2))

  • 匹配记录对象并解构字段
  • 必须完全匹配记录形状

示例:

dart
// 完整字段匹配
var (myString: foo, myNumber: bar) = (myString: 'string', myNumber: 1);

// 省略getter名称
var (:untyped, :int typed) = record;

// 带类型转换
var (untyped: untyped as int, typed: typed as String) = record;

对象模式 (SomeClass(x: subpattern1, y: subpattern2))

  • 通过对象属性getter解构数据
  • 类型不匹配时模式被拒绝

示例:

dart
switch (shape) {
  case Rect(width: var w, height: var h): // ...
}

特殊模式

通配符模式 (_)

  • 不绑定任何变量
  • 可作为占位符使用

示例:

dart
var [_, two, _] = [1, 2, 3];

带类型注解的通配符

用于类型测试而不绑定值:

dart
switch (record) {
  case (int _, String _): // 第一个字段是int,第二个是String
}

模式求值示例

dart
// 假设 x=true, y=true, z=false
x || y         => 匹配 true
x || y && z    => 匹配 true  (等价于 x || (y && z))
(x || y) && z  => 无匹配

Dart 求值顺序:

  1. x || y → true (因x为true)
  2. x || y && z → true (同上)
  3. (x || y) && z → false (z为false)

这个版本:
1. 使用清晰的标题层级
2. 代码块独立显示
3. 关键概念加粗强调
4. 示例与说明分离
5. 添加了目录导航
6. 保持了所有技术细节的准确性

您可以直接复制到支持Markdown的编辑器中查看最佳效果。需要进一步调整请随时告诉我。