分支
本页面介绍如何使用分支控制 Dart 代码的执行流程:
- if 语句和元素
- if-case 语句和元素
- switch 语句和表达式
你还可以通过以下方式操控 Dart 的执行流程:
- 循环结构(如
for和while) - 异常处理(如
try、catch和throw)
if 语句
Dart 支持带可选子句的语句。括号内的条件必须是评估为布尔值的表达式:if / else if
if (isRaining()) {
you.bringRainCoat();
} else if (isSnowing()) {
you.wearJacket();
} else {
car.putTopDown();
}若要在表达式上下文中使用 if,请参阅条件表达式。
if-case 语句
Dart 语句支持后接模式匹配的子句:if / case
if (pair case [int x, int y]) return Point(x, y);当模式与值匹配时,分支会执行,且模式中定义的变量会进入作用域。
前例中,列表模式 [int x, int y] 匹配了 pair 的值,因此分支执行时会将模式定义的变量 x 和 y 带入作用域,并返回 Point(x, y)。
若无匹配,控制流会继续执行后续分支(如果有):else
if (pair case [int x, int y]) {
print('坐标数组: $x,$y');
} else {
throw FormatException('无效坐标');
}if-case 语句提供了一种针对单一模式进行匹配和解构的方式。若需测试多个模式,请使用 switch。
版本说明:
if语句中的case子句需要 Dart 语言版本 ≥ 3.0。
switch 语句
switch 语句将一个值表达式与一系列 case 进行匹配。每个子句是待匹配的模式。switch 支持任意类型的模式。
当值匹配某个 case 的模式时,该分支体执行。非空子句完成后会跳转到 switch 末尾(无需显式 break)。其他合法结束方式包括 continue、throw 或 return 语句。
使用 default 或通配符 _ 子句处理无匹配情况:
var command = 'OPEN';
switch (command) {
case 'CLOSED': executeClosed();
case 'PENDING': executePending();
case 'APPROVED': executeApproved();
case 'DENIED': executeDenied();
case 'OPEN': executeOpen();
default: executeUnknown();
}空 case 会穿透到下一分支(共享执行体)。若需禁止穿透,用 break 作为空分支体。非连续穿透可通过 continue 和标签实现:
switch (command) {
case 'OPEN':
executeOpen();
continue newCase; // 跳转至 newCase 标签
case 'DENIED': // 空分支穿透
case 'CLOSED':
executeClosed(); // 同时处理 DENIED 和 CLOSED
newCase:
case 'PENDING':
executeNowClosed(); // 同时处理 OPEN 和 PENDING
}逻辑或模式(||)允许多个 case 共享执行体或守卫条件。更多模式与子句用法详见文档。
版本说明:
switch语句需要 Dart 语言版本 ≥ 3.0。
switch 表达式
switch 表达式根据匹配的 case 返回一个值。它可用于 Dart 允许表达式的任何位置(表达式语句开头除外)。例如:
var x = switch (y) { ... };
print(switch (x) { ... });
return switch (x) { ... };若需在表达式语句开头使用 switch,请改用 switch 语句。
switch 表达式可重构传统语句为更简洁的形式:
// 传统 switch 语句(使用常量变量 slash/star/comma/semicolon/digit0/digit9...)
switch (charCode) {
case slash || star || plus || minus:
token = operator(charCode);
case comma || semicolon:
token = punctuation(charCode);
case >= digit0 && <= digit9:
token = number();
default:
throw FormatException('无效字符');
}等价于表达式形式:
token = switch (charCode) {
slash || star || plus || minus => operator(charCode),
comma || semicolon => punctuation(charCode),
>= digit0 && <= digit9 => number(),
_ => throw FormatException('无效字符'),
};switch 表达式与语句的关键语法差异:
case前无需关键字- 分支体是单一表达式而非语句序列
- 每个
case必须显式定义分支体(无隐式穿透) - 模式与分支体用
=>分隔而非: - 分支间用
,分隔(允许末尾可选逗号) - 默认分支仅支持
=>(不可混合使用:)
版本说明:
switch表达式需要 Dart 语言版本 ≥ 3.0。
完备性检查
完备性检查会在编译时报告错误:若存在值可能进入 switch 却不匹配任何 case 的情况。
// 非完备 switch(缺失 null 分支)
switch (nullableBool) {
case true: print('yes');
case false: print('no');
}default 或 _ 分支可覆盖所有可能值,使 switch 对任意类型完备。
枚举和密封类型特别适合 switch——即使无 default 分支,其所有可能值也是已知且可枚举的。通过 sealed 修饰类,可在子类切换时启用完备性检查:
sealed class Shape {}
class Square implements Shape {
final double length;
Square(this.length);
}
class Circle implements Shape {
final double radius;
Circle(this.radius);
}
double calculateArea(Shape shape) => switch (shape) {
Square(length: var l) => l * l,
Circle(radius: var r) => math.pi * r * r,
};若后续新增 Shape 子类,该表达式将不完整,完备性检查会提示缺失的子类型。这种机制支持类似函数式代数数据类型的编程风格。
守卫子句
在 case 子句后添加可选守卫条件时,使用关键字 when。守卫可跟在 if 和 switch(语句或表达式)之后:
// switch 语句中的守卫
switch (something) {
case somePattern when some || boolean || expression:
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 守卫子句
body;
}
// switch 表达式中的守卫
var value = switch (something) {
somePattern when some || boolean || expression => body,
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 守卫子句
};
// if-case 语句中的守卫
if (something case somePattern when some || boolean || expression) {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 守卫子句
body;
}守卫会在模式匹配后评估任意布尔表达式,从而对分支执行添加额外约束。若守卫为 false,控制流会跳至下一 case 而非直接退出 switch。