一、邏輯或模式 A || B
符合任一子模式即匹配;所有分支必須定義完全相同的變數集合。
enum Color { red, yellow, blue, green }
void main() {
Color c = Color.red;
bool primary = switch(c) {
Color.red || Color.yellow || Color.blue => true,
_ => false
};
print(primary); // true
}Code language: Dart (dart)
二、邏輯與模式 A && B
兩個子模式必須同時匹配;各子模式不可綁定同名變數。
void main() {
switch((2, 3)) {
// 編譯錯誤:兩個子模式皆綁定變數b,發生變數名稱衝突
// case (var a, var b) && (var b, var c): print("ok");
case (var a, var b) && (>1, <5):
print("a=$a,b=$b"); // a=2,b=3
}
}Code language: Dart (dart)
此處 (>1, <5) 代表第一個數字必須大於1、第二個數字必須小於5。
三、關係運算子模式 < > <= >= == !=
用於數值區間判斷,常搭配 && 限定數值範圍
String asciiCharType(int charCode) {
const space = 32, zero = 48, nine = 57;
return switch(charCode) {
< space => "控制字元",
== space => "空白字元",
> space && < zero => "標點符號",
>= zero && <= nine => "數字",
_ => "其他字元"
};
}
void main() {
print(asciiCharType(50)); // 數字
print(asciiCharType(33)); // 標點符號
}Code language: Dart (dart)
以上範例使用 ASCII 編碼,用來定義控制字元、數字與符號。傳入switch的charCode判斷規則:小於32為控制字元、等於32為空白、介於32至48之間為標點、48到57為數字,其餘歸類為其他。
四、強制轉型模式 sub as Type
解構過程中強制轉換型別,若型別不匹配則執行時拋出例外
void main() {
(num, Object) rec = (10, "hello");
var (i as int, s as String) = rec;
print(i + 5); // 15
print(s.toUpperCase()); // HELLO
}Code language: Dart (dart)
本範例將rec解構至i與s,若rec第一項非整數、第二項非字串,將觸發執行例外。
以下為錯誤示範:
void main() {
(num, Object) rec = (9.3, "hello");
var (i as int, s as String) = rec;
print(i + 5); // 15
print(s.toUpperCase()); // HELLO
}Code language: Dart (dart)
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Unhandled exception:
type 'double' is not a subtype of type 'int' in type cast
#0 main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:3:10)
#1 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#2 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)
五、空值檢查模式 sub?
僅非空值會匹配,內部變數自動升級為不可空型別;null直接匹配失敗,不會拋出錯誤。
void main() {
String? str = "test";
switch(str) {
case var s?:
print(s.length); // s為不可空字串,輸出4
case null:
print("空值");
}
}Code language: Dart (dart)
六、空值斷言模式 sub!
僅非空值會匹配;若值為null,直接拋出執行時例外。
void main() {
List<String?> row = ["user", "bob"];
switch(row) {
case ["user", var name!]:
print(name); // name為不可空字串
}
// 用於變數解構
(int?, int?) pos = (2, 3);
var (x!, y!) = pos;
print(x + y);
}Code language: Dart (dart)
var name! 拆解說明
var name:變數模式 —var宣告全新區域變數name,匹配成功後綁定值;!:後置空值斷言模式 — 要求當前值不可為null,若為null則執行階段報錯。
合併含義:var name! 建立新變數name,同時強制斷言該值一定非空。
七、常數模式
字面量、具名常數、const建構子、const集合皆屬常數模式,值相等即匹配。
支援:數字、字串、布林、具名常數、const 物件 / 串列
void main() {
const target = 10;
int num = 10;
switch(num) {
case 1: print("一");
case target: print("符合常數10");
case const [1,2]: print("常數串列");
default: print("其他");
}
}Code language: Dart (dart)
執行輸出
符合常數10
八、變數模式 var x / int x / final x
匹配成功後綁定新區域變數;加上型別會同步驗證值的型別。
void main() {
switch((99, "dart")) {
case (int a, String b):
print("$a $b"); // 99 dart
case (int a, int b):
print("兩個數值");
}
}Code language: Dart (dart)
九、識別元模式
依使用場景分三種行為:
- 宣告語境
var (a,b):建立新變數 - 賦值語境
(a,b) = val:覆蓋既有變數 - switch比對語境:視為常數(
_除外)
void main() {
const c = 5;
int val = 2;
switch(val) {
case c: print("匹配常數c");
default: print("無匹配"); // 執行此行
}
}
Code language: Dart (dart)
十、括號模式 (subPattern)
調整模式運算子優先順序,釐清 || 與 && 的執行順序
void main() {
bool x = true, y = true, z = false;
bool test = switch(true) {
(x || y) && z => true,
_ => false
};
print(test); // false
}
Code language: Dart (dart)
十一、串列模式
匹配List物件,依位置解構元素;支援 ... rest運算子擷取任意數量剩餘元素
1. 基礎串列匹配
void main() {
const a = "a", b = "b";
var arr = ["a", "b"];
switch(arr) {
case [a, b]: print("匹配成功");
default: print("無匹配");
}
}Code language: Dart (dart)
2. rest剩餘元素擷取
void main() {
var [a, b, ...rest, c, d] = [1,2,3,4,5,6,7];
print("$a $b $rest $c $d"); // 1 2 [3, 4, 5] 6 7
}
Code language: Dart (dart)
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
1 2 [3, 4, 5] 6 7Code language: CSS (css)
十二、Map模式 {"key": subP}
匹配Map物件,僅驗證指定鍵;目標鍵不存在時拋出 StateError,未提及的多餘鍵直接忽略
void main() {
var data = {"user": ["Lily", 13]};
if(data case {"user": [String name, int age]}) {
print("$name $age"); //Lily 13
}
}Code language: JavaScript (javascript)
十三、記錄模式
分兩種:位置記錄 (p1,p2)、具名記錄 (k:p1,k2:p2)
支援 :var 簡寫語法,省略重複欄位名稱
void main() {
// 位置記錄解構
var (name, age) = ("Doug", 25);
// 具名欄位簡寫解構
final (:name, :age) = (name: "Tom", age: 18);
}
Code language: JavaScript (javascript)
十四、物件模式 Class(prop: p)
匹配指定型別物件,解構Getter屬性;支援 :var 簡寫
class Point {
final int x, y;
Point(this.x, this.y);
}
void main() {
Point p = Point(10, 20);
var Point(:x, :y) = p;
print("$x $y");
}
Code language: JavaScript (javascript)
十五、萬用字元模式 _
匹配任意值,不綁定變數;用作佔位、僅驗證型別而不取內容
void main() {
var arr = [1,2,3];
var [_, mid, _] = arr;
print(mid); // 2
switch((10, "abc")) {
case (int _, String _):
print("型別匹配成功");
}
}Code language: JavaScript (javascript)
Pattern