分支
本页面展示了如何使用分支控制 Dart 代码的流程:
if
语句和表达式if-case
语句和表达式switch
语句和表达式
您还可以使用以下方法操作 Dart 中的控制流:
- [循环][loops],例如
for
和while
- [异常][exceptions],例如
try
、catch
和throw
If
#Dart 支持带可选 else
子句的 if
语句。 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
匹配,因此分支 return Point(x, y)
将执行模式定义的变量 x
和 y
。
否则,控制流将继续到 else
分支执行,如果存在的话:
if (pair case [int x, int y]) {
print('Was coordinate array $x,$y');
} else {
throw FormatException('Invalid coordinates.');
}
if-case
语句提供了一种匹配和 解构 单个模式的方法。要根据多个模式测试值,请使用 switch 。
Switch 语句
#switch
语句将值表达式与一系列情况进行评估。每个 case
子句都是要匹配的值的 模式 。您可以对情况使用 任何类型的模式 。
当值与情况的模式匹配时,将执行情况体。非空 case
子句在完成之后跳转到 switch
的末尾。它们不需要 break
语句。结束非空 case
子句的其他有效方法是 continue
、 throw
或 return
语句。
使用 default
或 通配符 _
子句在没有 case
子句匹配时执行代码:
var command = 'OPEN';
switch (command) {
case 'CLOSED':
executeClosed();
case 'PENDING':
executePending();
case 'APPROVED':
executeApproved();
case 'DENIED':
executeDenied();
case 'OPEN':
executeOpen();
default:
executeUnknown();
}
空情况会贯穿到下一个情况,允许情况共享主体。对于不贯穿的空情况,请使用 break
作为其主体。对于非顺序贯穿,您可以使用 continue
语句 和标签:
switch (command) {
case 'OPEN':
executeOpen();
continue newCase; // 继续在新情况标签处执行。
case 'DENIED': // 空情况贯穿。
case 'CLOSED':
executeClosed(); // 对 DENIED 和 CLOSED 都运行,
newCase:
case 'PENDING':
executeNowClosed(); // 对 OPEN 和 PENDING 都运行。
}
您可以使用 逻辑或模式 允许情况共享主体或保护。要了解有关模式和情况子句的更多信息,请查看有关 Switch 语句和表达式 的模式文档。
Switch 表达式
#switch
表达式 根据匹配的任何情况的表达式主体生成一个值。您可以在 Dart 允许表达式的任何地方使用 switch
表达式, 但 不能在表达式语句的开头使用。例如:
var x = switch (y) { ... };
print(switch (x) { ... });
return switch (x) { ... };
如果要在表达式语句的开头使用 switch
,请使用 switch 语句 。
switch
表达式允许您重写如下所示的 switch
语句 :
// slash、star、comma、semicolon 等是常量变量……
switch (charCode) {
case slash || star || plus || minus: // 逻辑或模式
token = operator(charCode);
case comma || semicolon: // 逻辑或模式
token = punctuation(charCode);
case >= digit0 && <= digit9: // 关系和逻辑与模式
token = number();
default:
throw FormatException('Invalid');
}
转换为如下所示的 表达式 :
token = switch (charCode) {
slash || star || plus || minus => operator(charCode),
comma || semicolon => punctuation(charCode),
>= digit0 && <= digit9 => number(),
_ => throw FormatException('Invalid')
};
switch
表达式的语法与 switch
语句语法不同:
- 情况 不 以
case
关键字开头。 - 情况体是一个表达式,而不是一系列语句。
- 每个情况都必须有一个主体;空情况没有隐式贯穿。
- 使用
=>
而不是:
将情况模式与它们的主体分开。 - 用
,
分隔情况(允许可选的尾随,
)。 - 默认情况 只能 使用
_
,而不是同时允许default
和_
。
完备性检查
#完备性检查是一项功能,如果可能有一个值进入 switch
但与任何情况都不匹配,则会报告编译时错误。
// 对 bool? 的非完备 switch,缺少匹配 null 可能性的情况:
switch (nullableBool) {
case true:
print('yes');
case false:
print('no');
}
默认情况( default
或 _
)涵盖了可以流经 switch
的所有可能值。这使得对任何类型的 switch
都很完备。
枚举 和 密封类型 对于 switch
特别有用,因为即使没有默认情况,它们的可能值也是已知且完全可枚举的。对类使用 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
的新子类,则此 switch
表达式将不完整。完备性检查会通知您缺少的子类型。这允许您以某种 函数式代数数据类型样式 使用 Dart。
保护子句
#要在 case
子句后设置可选保护子句,请使用关键字 when
。保护子句可以在 if case
后面,以及 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 时,执行将继续到下一个情况,而不是退出整个 switch
。
除非另有说明,否则本网站上的文档反映的是 Dart 3.6.0。页面最后更新于 2025-02-05。 查看源代码 或 报告问题.