内容

此页面展示了如何使用分支控制 Dart 代码的流程

  • if 语句和元素
  • if-case 语句和元素
  • switch 语句和表达式

你还可以使用以下方式在 Dart 中操作控制流

  • 循环,例如 forwhile
  • 异常,例如 trycatchthrow

If

#

Dart 支持带有可选 else 子句的 if 语句。if 后括号中的条件必须是一个求值为 布尔值 的表达式

dart
if (isRaining()) {
  you.bringRainCoat();
} else if (isSnowing()) {
  you.wearJacket();
} else {
  car.putTopDown();
}

如需了解如何在表达式上下文中使用 if,请查看 条件表达式

If-case

#

Dart if 语句支持后面跟有 模式case 子句

dart
if (pair case [int x, int y]) return Point(x, y);

如果模式与值匹配,则该分支将执行,并使用模式在范围内定义的任何变量。

在上一个示例中,列表模式 [int x, int y] 与值 pair 匹配,因此分支 return Point(x, y) 使用模式定义的变量 xy 执行。

否则,如果存在 else 分支,则控制流将继续执行该分支

dart
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 子句都是要与之匹配的值的 模式。您可以对 case 使用 任何类型的模式

当值与 case 的模式匹配时,case 主体会执行。非空 case 子句在完成之后会跳到 switch 的末尾。它们不需要 break 语句。结束非空 case 子句的其他有效方法是 continuethrowreturn 语句。

使用 default通配符 _ 子句在没有 case 子句匹配时执行代码

dart
var command = 'OPEN';
switch (command) {
  case 'CLOSED':
    executeClosed();
  case 'PENDING':
    executePending();
  case 'APPROVED':
    executeApproved();
  case 'DENIED':
    executeDenied();
  case 'OPEN':
    executeOpen();
  default:
    executeUnknown();
}

空 case 会贯穿到下一个 case,允许 case 共享一个主体。对于不会贯穿的空 case,请为其主体使用 break。对于非顺序贯穿,您可以使用 continue 语句 和一个标签

dart
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 共享一个主体或一个保护。如需详细了解模式和 case 子句,请查看 switch 语句和表达式 上的模式文档。

Switch 表达式

#

switch 表达式会根据匹配的 case 的表达式主体生成一个值。您可以在 Dart 允许表达式的任何地方使用 switch 表达式,表达式语句的开头除外。例如

dart
var x = switch (y) { ... };

print(switch (x) { ... });

return switch (x) { ... };

如果您想在表达式语句的开头使用 switch,请使用 switch 语句

Switch 表达式允许你重写类似这样的 switch 语句

dart
// 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');
}

变成类似这样的 表达式

dart
token = switch (charCode) {
  slash || star || plus || minus => operator(charCode),
  comma || semicolon => punctuation(charCode),
  >= digit0 && <= digit9 => number(),
  _ => throw FormatException('Invalid')
};

switch 表达式的语法与 switch 语句语法不同

  • case 关键字开头。
  • Case 主体是一个单独的表达式,而不是一系列语句。
  • 每个 case 都必须有一个主体;对于空 case 来说,没有隐式贯穿。
  • Case 模式使用 => 而不是 : 与其主体分隔。
  • Case 使用 , 分隔(并且允许一个可选的尾随 ,)。
  • 默认 case 只能使用 _,而不是允许 default_

穷举性检查

#

穷举性检查是一项功能,如果一个值可能进入 switch 但不匹配任何 case,它会报告一个编译时错误。

dart
// Non-exhaustive switch on bool?, missing case to match null possibility:
switch (nullableBool) {
  case true:
    print('yes');
  case false:
    print('no');
}

一个默认 case(default_)涵盖了所有可能流经 switch 的值。这使得对任何类型的 switch 都是穷举性的。

枚举密封类型 对 switch 特别有用,因为即使没有默认 case,它们可能的值也是已知的并且是完全可枚举的。在类上使用 sealed 修饰符,以便在切换该类的子类型时启用穷举性检查

dart
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 语句和表达式。

dart
// 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;
}

保护在匹配 之后 计算一个任意的布尔表达式。这允许你添加进一步的约束,以确定是否应该执行 case 主体。当保护子句计算为 false 时,执行将继续到下一个 case,而不是退出整个 switch。