一、if /if-else 基础分支
if括号内必须是布尔表达式,不能隐式转布尔- 支持多段
else if,最后可选else - 单行可省略大括号,推荐统一加花括号提升可读性
void main() {
bool isRaining = false;
bool isSnowing = true;
if (isRaining) {
print("带雨衣");
} else if (isSnowing) {
print("穿厚外套");
} else {
print("开敞篷车");
}
}Code language: Dart (dart)
执行结果
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
穿厚外套Code language: CSS (css)
也可以单独使用if
void main() {
bool isRaining = false;
bool isSnowing = true;
if (isRaining) {
print("带雨衣");
}
}Code language: Dart (dart)
或者就if else
void main() {
bool isRaining = false;
bool isSnowing = true;
if (isRaining) {
print("带雨衣");
} else {
print("开敞篷车");
}
}Code language: Dart (dart)
二、if-case 模式匹配分支(Dart3.0+)
- 匹配模式,匹配成功则解构绑定变量到当前作用域
- 匹配失败走 else;支持
when守卫追加布尔判断 - 只针对单个值单模式匹配,多模式匹配用 switch
void main() {
final pair = [100, 220];
// 匹配长度2、两个int的列表
if (pair case [int x, int y]) {
print("坐标:$x,$y");
} else {
throw FormatException("无效坐标");
}
}Code language: Dart (dart)
执行结果
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
坐标:10,20Code language: CSS (css)
2:if-case 结合 when 守卫
void main() {
final data = [8, 9];
if (data case [int a, int b] when a > 5 && b > 5) {
print("两个数字都大于5");
} else {
print("数字不满足条件");
}
}Code language: Dart (dart)
执行结果
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
两个数字都大于5Code language: CSS (css)
三、switch 语句
传统 switch,语句形式,没有返回值
- case 支持任意模式:字符串、常量、逻辑或、关系模式
- 非空 case 自动 break,不用手动写 break;空 case 自动穿透
- 手动穿透两种方式:
continue 标签/ 空 case 连续写 default最终都不匹配的时候就执行;支持when守卫
1:基础字符串匹配
void main() {
String command = "OPEN";
switch (command) {
case "CLOSED":
print("执行关闭逻辑");
case "PENDING":
print("执行等待逻辑");
case "OPEN":
print("执行打开逻辑");
default:
print("未知指令");
}
}
Code language: Dart (dart)
执行结果
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
执行打开逻辑Code language: CSS (css)
2:空 case 穿透 + continue 标签跳转
String command = "OPEN";
switch (command) {
case "OPEN":
print("打开操作"); // ① 匹配到 OPEN,执行打印
continue newCase; // ② 直接跳转到 newCase: 位置,不再回头
case "DENIED":
case "CLOSED":
print("关闭操作");
newCase: // ③ 跳转目标点
case "PENDING":
print("待处理统一逻辑"); // ④ 直接执行这里,不会判断 command == "PENDING"
}Code language: Dart (dart)
执行结果
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
打开操作
待处理统一逻辑Code language: CSS (css)
这个例子中 continue newCase; 是不是就跳转到了newCase: 这里 但是下一个 case “PENDING”: 不是不匹配吗 为什么还会执行print(“待处理统一逻辑”);?
应该很多读者有这个疑问
continue label; 不会重新匹配值,而是直接跳转到标签所在的 case 分支入口,不再做条件判断,直接执行分支内代码。
3:switch + when
void main() {
int score = 88;
switch (score) {
case int s when s >= 90:
print("优秀");
case int s when s >= 60:
print("及格");
default:
print("不及格");
}
}
Code language: Dart (dart)
输出及格
先匹配类型 发现必须都是int类型,如果是int类型 就赋值给s ,如果符合后,再进行后面的when守卫,它进行二次校验,如果s的值符合 when后面的条件,才执行case后面的语句。再这里,虽然又两个int s 但是作用域是不一样的。
每个 case int s 是各自独立的模式绑定,作用域只在当前这个 case 分支内部,互不干扰
你完全可以给两个不同的变量名。效果一模一样。
switch (score) {
case int a when a >= 90:
print("优秀");
case int b when b >= 60:
print("及格");
default:
print("不及格");
}Code language: Dart (dart)
四、switch 表达式
需要是Dart3.0+后才支持的语法,有返回值,常用赋值
和 switch 语句区别
- 无
case关键字,用=>分隔模式与表达式 - 每个分支必须返回表达式,逗号分隔分支
- 无隐式穿透,每个分支独立;最终都不匹配的时候用下划线
_不能用 default - 可直接赋值、print、return,所有表达式通用
1:基础字符运算符匹配(逻辑或模式)
void main() {
const slash = 47, star = 42, comma = 44;
int charCode = 42;
final token = switch (charCode) {
slash || star => "运算符",
comma => "标点",
_ => "无效字符"
};
print(token);
}
Code language: Dart (dart)
运行结果
运算符
本例子中,规定了三个符号的ASCII码的常量,然后有一个是变量charCode ,然后下面判断这个变量,是否属于运算符或者标点符号,还是其他的符号。
2:switch 表达式 + when 守卫
void main() {
int age = 22;
String level = switch (age) {
int a when a < 18 => "未成年",
int a when a < 30 => "青年",
_ => "成年"
};
print(level);
}Code language: Dart (dart)
运行结果
青年
3:函数 return 中直接使用 switch 表达式
void main() {
print(getDesc(3));
}
String getDesc(int num) => switch (num) {
1 => "一",
2 => "二",
_ => "其他数字"
};
Code language: Dart (dart)
执行结果
其他数字
注意:这里是switch是表达式,然后getDesc是一个箭头函数,箭头函数是dart区别其他类C语言的一个语法。
五、穷尽性校验 Exhaustiveness Checking
编译报错:当传入值存在无法匹配的分支,强制补全 case;密封类 sealed、enum 天然支持穷尽校验,不需要 _ / default。
1:可空布尔 非穷尽报错(读者可以注释运行看报错)
void main() {
bool? nullableBool = null;
// 下面代码取消注释会编译报错:缺少null匹配分支,同时也没有default _的兜底
/*
switch (nullableBool) {
case true:
print("是");
case false:
print("否");
}
*/
// 修复:增加null分支或_兜底
switch (nullableBool) {
case true:
print("是");
case false:
print("否");
case null:
print("空值");
}
}Code language: PHP (php)
执行结果
空值
2:sealed 密封类
代数数据类型,强制穷尽匹配
import 'dart:math' as math;
// 密封类:只能在当前文件实现子类
sealed class Shape {}
// 子类 方形边长
class Square implements Shape {
final double length;
Square(this.length);
}
//子类 圆形半径
class Circle implements Shape {
final double radius;
Circle(this.radius);
}
//一个箭头函数根据传入的子类对象进行switch匹配调用那个函数
double calculateArea(Shape shape) => switch (shape) {
Square(length: var l) => l * l,
Circle(radius: var r) => math.pi * r * r
// 新增Shape子类会直接编译报错,提示缺少对应case
};
void main() {
final Shape circle = Circle(5);
print(calculateArea(circle));
final Shape square = Square(4);
print(calculateArea(square));
}
Code language: Dart (dart)
执行结果
78.53981633974483
16.0Code language: CSS (css)
3:Enum 枚举穷尽匹配
不需要下划线_兜底
void main() {
final Animal animal = Animal.cat;
String name = switch (animal) {
Animal.dog => "小狗",
Animal.cat => "小猫"
};
print(name);
}
enum Animal { dog, cat }
Code language: Dart (dart)
输出小猫
由于enum枚举已经又一定的范围,不会出现其他值了,所以不需要兜底。
六、when 守卫
if-case /switch 语句 /switch 表达式全覆盖
when 作用:模式匹配成功后,再追加布尔判断;守卫 false 则进入下一分支,不会退出 switch。
1. if-case + when
void main() {
List<int> arr = [10, 20];
if (arr case [int x, int y] when x + y > 20) {
print("两数之和大于20");
}
}Code language: Dart (dart)
两数之和大于20
先匹配类型 是不是两个int的列表,符合后再使用when来判断它们的和是不是大于20
2. switch 语句 + when
void main() {
int num = 15;
switch(num) {
case int n when n % 2 == 0:
print("偶数");
case int n when n % 2 != 0:
print("奇数");
}
}
Code language: PHP (php)
输出 奇数
先判断int类型,然后判断when。
3. switch 表达式 + when
void main() {
int num = 15;
String res = switch(num) {
int n when n % 2 == 0 => "偶数",
_ => "奇数"
};
print(res);
}
Code language: PHP (php)