分支
本頁介紹如何使用分支來控制 Dart 程式碼的執行流程
if語句和元素if-case語句和元素switch語句和表示式
你還可以透過以下方式在 Dart 中操作控制流:
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 子句都是一個模式,用於匹配該值。你可以為 case 使用任何型別的模式。
當值與 case 的模式匹配時,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();
}空 case 會貫穿到下一個 case,允許 case 共享主體。對於不貫穿的空 case,請使用 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 共享主體或守衛。要了解有關模式和 case 子句的更多資訊,請查閱Switch 語句和表示式上的模式文件。
Switch 表示式
#switch 表示式根據匹配的 case 的表示式主體生成一個值。你可以在 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 不以
case關鍵字開頭。 - case 主體是單個表示式,而不是一系列語句。
- 每個 case 必須有一個主體;空 case 沒有隱式貫穿。
- case 模式與其主體之間使用
=>分隔,而不是:。 - case 之間用
,分隔(允許可選的末尾,)。 - 預設 case 只能使用
_,而不允許同時使用default和_。
窮盡性檢查
#窮盡性檢查是一項功能,如果某個值可能進入 switch 但不匹配任何 case,它會報告編譯時錯誤。
// 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 修飾符,以便在切換該類的子型別時啟用窮盡性檢查。
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;
}守衛在匹配之後評估一個任意的布林表示式。這允許你對 case 主體是否應該執行新增進一步的約束。當守衛子句評估為 false 時,執行將繼續到下一個 case,而不是退出整個 switch。