本页展示了如何使用分支控制 Dart 代码的流程:
- if 语句和元素
- if-case 语句和元素
- switch 语句和表达式
您还可以使用以下方法操纵 Dart 中的控制流:
- 循环,例如 for 和 while
- 例外,例如 try 、 catch 和 throw
If
Dart 支持带有可选 else 子句的 if 语句。 if 后面括号中的条件必须是计算结果为布尔值的表达式:
if (isRaining()) {
you.bringRainCoat();
} else if (isSnowing()) {
you.wearJacket();
} else {
car.putTopDown();
}
要了解如何在表达式上下文中使用 if ,请查看条件表达式。
如果情况
Dart if 语句支持 case 子句后跟一个模式:
if (pair case [int x, int y]) return Point(x, y);
如果模式与值匹配,则分支将使用模式在范围内定义的任何变量执行。
在前面的示例中,列表模式 [int x, int y] 与值 pair 匹配,因此分支 return Point(x, y) 使用该模式定义的变量 x 。
否则,控制流前进到 else 分支执行(如果有):
if (pair case [int x, int y]) {
print('Was coordinate array $x,$y');
} else {
throw FormatException('Invalid coordinates.');
}
if-case 语句提供了一种针对单个模式进行匹配和解构的方法。要针对多种模式测试某个值,请使用 switch。
if 语句中的 Case 子句要求语言版本至少为 3.0。
Switch 语句
switch 语句根据一系列情况计算值表达式。每个 case 子句都是要匹配的值的模式。您可以在案例中使用任何类型的图案。
当该值与案例的模式匹配时,案例主体就会执行。非空 case 子句在完成后跳转到 switch 的末尾。它们不需要 break 语句。结束非空 case 子句的其他有效方法是 continue 、 throw 或 return 语句。
当没有 case 子句匹配时,使用 default 或通配符 _ 子句执行代码:
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; // Continues executing at the newCase label.
case 'DENIED': // Empty case falls through.
case 'CLOSED':
executeClosed(); // Runs for both DENIED and CLOSED,
newCase:
case 'PENDING':
executeNowClosed(); // Runs for both OPEN and PENDING.
}
您可以使用逻辑或模式来允许案例共享主体或防护。要了解有关模式和 case 子句的更多信息,请查看有关 Switch 语句和表达式的模式文档。
切换表达式
switch 表达式根据大小写匹配的表达式主体生成一个值。您可以在 Dart 允许表达式的任何地方使用 switch 表达式,但表达式语句的开头除外。例如:
var x = switch (y) { ... };
print(switch (x) { ... });
return switch (x) { ... };
如果要在表达式语句的开头使用 switch,请使用 switch 语句。
Switch 表达式允许您像这样重写 switch 语句:
// Where slash, star, comma, semicolon, etc., are constant variables...
switch (charCode) {
case slash || star || plus || minus: // Logical-or pattern
token = operator(charCode);
case comma || semicolon: // Logical-or pattern
token = punctuation(charCode);
case >= digit0 && <= digit9: // Relational and logical-and patterns
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 和 _ 。
witch 表达式需要至少 3.0 的语言版本。
详尽性检查
详尽性检查是一项功能,如果某个值可能进入开关但与任何情况都不匹配,则会报告编译时错误。
// Non-exhaustive switch on bool?, missing case to match null possibility:
switch (nullableBool) {
case true:
print('yes');
case false:
print('no');
}
默认情况( 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 的新子类,则此 switch 表达式将不完整。详尽检查将告知您缺少的子类型。这允许您以某种函数式代数数据类型风格使用 Dart。
保护条款
要在 case 子句后设置可选的保护子句,请使用关键字 when 。保护子句可以跟在 if case 以及 switch 语句和表达式之后。
// Switch statement:
switch (something) {
case somePattern when some || boolean || expression:
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Guard clause.
body;
}
// Switch expression:
var value = switch (something) {
somePattern when some || boolean || expression => body,
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Guard clause.
}
// If-case statement:
if (something case somePattern when some || boolean || expression) {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Guard clause.
body;
}
守卫在匹配后评估任意布尔表达式。这允许您添加关于是否应执行案例主体的进一步约束。当保护子句的计算结果为 false 时,执行将继续执行下一个 case,而不是退出整个 switch。