內容

此頁面說明如何使用分支控制 Dart 程式碼的流程

  • if 陳述式和元素
  • if-case 陳述式和元素
  • switch 陳述式和表達式

您也可以使用以下方式來控制 Dart 中的流程

  • 迴圈,例如 forwhile
  • 例外,例如 trycatchthrow

如果

#

Dart 支援 if 陳述式,並提供選用的 else 子句。if 後括號中的條件必須是會評估為 布林值 的運算式

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

如要了解如何在運算式內容中使用 if,請參閱 條件式運算式

如果-情況

#

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.
}

你可以使用 邏輯或模式 讓案例共用主體或防護。如需深入了解模式和案例子句,請查看 Switch 陳述式和表達式 中的模式文件。

Switch 表達式

#

switch 表達式會根據與哪個案例相符的表達式主體產生一個值。你可以在 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 關鍵字開頭。
  • 案例主體是單一表達式,而不是一系列陳述式。
  • 每個案例都必須有一個主體;沒有空案例的隱式穿透。
  • 案例模式使用 => 而不是 : 與其主體分隔。
  • 案例使用 , 分隔(並且允許選擇性尾隨 ,)。
  • 預設案例只能使用 _,而不是同時允許 default_

窮舉性檢查

#

窮舉性檢查是一種功能,如果值有可能進入 switch 但與任何案例都不相符,它會報告編譯時期錯誤。

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

預設案例(default_)涵蓋所有可能流經 switch 的值。這使得任何類型的 switch 都很詳盡。

列舉密封類型 對 switch 特別有用,因為即使沒有預設案例,它們的可能值也是已知的且完全可列舉的。在類別上使用 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;
}

防護會在匹配之後評估任意布林表達式。這允許你進一步限制案例主體是否應該執行。當防護子句評估為 false 時,執行會繼續進行到下一個案例,而不是退出整個 switch。