Pattern 类型

一、逻辑或模式 A || B

匹配任意一个子模式;分支必须定义完全相同变量集合。

enum Color { red, yellow, blue, green }
void main() {
  Color c = Color.red;
  bool primary = switch(c) {
    Color.red || Color.yellow || Color.blue => true,
    _ => false
  };
  print(primary); // true
}Code language: Dart (dart)

二、逻辑与模式 A && B

两个子模式必须同时匹配;子模式不能绑定同名变量。

void main() {
  switch((2, 3)) {
    // 报错:两个子模式都绑定b,变量冲突
    // case (var a, var b) && (var b, var c): print("ok");
    case (var a, var b) && (>1, <5):
      print("a=$a,b=$b"); // a=2,b=3
  }
}Code language: Dart (dart)

这里是 (>1, <5) 就是要求第一个数字大于1 ,第二个数字小于5

三、关系模式 < > <= >= == !=

用于数值区间判断,常搭配 && 做范围限制

String asciiCharType(int charCode) {
  const space = 32, zero = 48, nine = 57;
  return switch(charCode) {
    < space => "控制字符",
    == space => "空格",
    > space && < zero => "标点",
    >= zero && <= nine => "数字",
    _ => "其他"
  };
}
void main() {
  print(asciiCharType(50)); // 数字
  print(asciiCharType(33)); // 标点
}Code language: Dart (dart)

以上例子用到了ASCII码,是用来记录符合数字控制符等等。 switch传入charCode 如果小于32 则表示控制字符,如果等于32则表示空格,如果大于32小于48则表示标点符号,如果大于等于48小57则表示是数字,否则就表示其他。

四、强转模式 sub as Type

解构中途强制类型转换,类型不符运行抛异常

void main() {
  (num, Object) rec = (10, "hello");
  var (i as int, s as String) = rec;
  print(i + 5); // 15
  print(s.toUpperCase()); // HELLO
}Code language: Dart (dart)

本例子中rec解构到i s中 如果rec中第一个不是int,第二个不是字符串,则会抛出异常

例如下面

void main() {
  (num, Object) rec = (9.3, "hello");
  var (i as int, s as String) = rec;
  print(i + 5); // 15
  print(s.toUpperCase()); // HELLO
}Code language: Dart (dart)
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Unhandled exception:
type 'double' is not a subtype of type 'int' in type cast
#0      main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:3:10)
#1      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#2      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)

五、空校验模式 sub?

值非空才匹配,内部变量自动转为非可空类型;null 直接匹配失败,不抛错

void main() {
  String? str = "test";
  switch(str) {
    case var s?:
      print(s.length); // s 是非空 String 输出4
    case null:
      print("空值");
  }
}Code language: Dart (dart)

六、空断言模式 sub!

值非空才匹配;如果是 null 直接抛出运行时异常

void main() {
  List<String?> row = ["user", "bob"];
  switch(row) {
    case ["user", var name!]:
      print(name); // name 非空 String
  }

  // 变量解构使用
  (int?, int?) pos = (2, 3);
  var (x!, y!) = pos;
  print(x + y);
}Code language: Dart (dart)

var name! 解析

  • var name变量模式 var 代表声明一个全新局部变量 name,匹配成功后把值绑定给它;
  • !空断言后置模式 要求当前值不能为 null,如果是 null 直接运行时报错。

合起来:var name! = 先新建变量 name,同时强制断言该值非空。

七、常量模式

字面量、常量、const 构造、const 集合都属于常量模式,值相等即匹配

支持:数字、字符串、布尔、命名常量、const 对象 / 列表

void main() {
  const target = 10;
  int num = 10;
  switch(num) {
    case 1: print("一");
    case target: print("等于常量10");
    case const [1,2]: print("常量列表");
    default: print("其他");
  }
}Code language: Dart (dart)

运行结果

等于常量10

八、变量模式 var x / int x / final x

匹配成功后绑定新局部变量;带类型则同时校验类型

void main() {
  switch((99, "dart")) {
    case (int a, String b):
      print("$a $b"); // 99 dart
    case (int a, int b):
      print("两个数字");
  }
}Code language: Dart (dart)

九、标识符模式

行为分三种场景:

  1. 声明上下文 var (a,b):新建变量
  2. 赋值上下文 (a,b) = val:覆盖已有变量
  3. switch 匹配上下文:当作常量(_ 除外)
void main() {
  const c = 5;
  int val = 2;
  switch(val) {
    case c: print("匹配常量c");
    default: print("不匹配"); // 输出
  }
}
Code language: Dart (dart)

十、括号模式 (subPattern)

修改模式运算优先级,区分 ||&& 结合顺序

void main() {
  bool x = true, y = true, z = false;
  bool test = switch(true) {
    (x || y) && z => true,
    _ => false
  };
  print(test); // false
}
Code language: Dart (dart)

十一、列表模式

匹配 List,按位置解构;支持 ... rest 忽略任意数量元素

1. 基础列表匹配
void main() {
  const a = "a", b = "b";
  var arr = ["a", "b"];
  switch(arr) {
    case [a, b]: print("匹配");
    default: print("不匹配");
  }
}Code language: Dart (dart)
2. rest 剩余元素捕获
void main() {
  var [a, b, ...rest, c, d] = [1,2,3,4,5,6,7];
  print("$a $b $rest $c $d"); // 1 2 [3, 4, 5] 6 7
}
Code language: Dart (dart)
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
1 2 [3, 4, 5] 6 7Code language: CSS (css)

十二、Map 模式 {"key": subP}

匹配 Map,只校验指定 key;key 不存在抛 StateError,多余 key 忽略

void main() {
  var data = {"user": ["Lily", 13]};
  if(data case {"user": [String name, int age]}) {
    print("$name $age"); //Lily 13
  }
}Code language: JavaScript (javascript)

十三、记录模式

两种:位置记录 (p1,p2)、具名记录 (k:p1,k2:p2)

支持简写 :var 省略重复字段名

void main() {
  // 位置记录解构
  var (name, age) = ("Doug", 25);
  // 具名字段简写解构
  final (:name, :age) = (name: "Tom", age: 18);
}
Code language: JavaScript (javascript)

十四、对象模式 Class(prop: p)

匹配指定类型对象,解构 getter 属性;简写 :var

class Point {
  final int x, y;
  Point(this.x, this.y);
}

void main() {
  Point p = Point(10, 20);
  var Point(:x, :y) = p;
  print("$x $y");
}
Code language: JavaScript (javascript)

十五、通配符模式 _

匹配任意值,不绑定变量;用于占位、仅校验类型不取值

void main() {
  var arr = [1,2,3];
  var [_, mid, _] = arr;
  print(mid); // 2

  switch((10, "abc")) {
    case (int _, String _):
      print("类型匹配");
  }
}Code language: JavaScript (javascript)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注