跳到主要內容

分支

本頁介紹如何使用分支來控制 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 語句。

當沒有 case 子句匹配時,使用 default萬用字元 _ 子句來執行程式碼。

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 之間用 , 分隔(允許可選的末尾 ,)。
  • 預設 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。