跳转到正文
YGJoon 技术博客

Dart 控制流语句详解

发布于:
·1.1k 字 · 约 3 分钟·作者:
if-else、switch-case、三种 for 循环、while 与 do-while,加上 break 和 continue 跳出规则,控制流一次配齐。
Dart 控制流语句详解文章封面
目录

if-else 语句

基本的条件控制:

int age = 20;

if (age >= 18) {
  print("成年人");
} else if (age >= 12) {
  print("青少年");
} else {
  print("儿童");
}

switch-case 语句

多分支条件控制:

String grade = 'A';

switch (grade) {
  case 'A':
    print("优秀");
    break;
  case 'B':
    print("良好");
    break;
  case 'C':
    print("及格");
    break;
  default:
    print("不及格");
}

for 循环

标准 for 循环

for (int i = 0; i < 5; i++) {
  print(i); // 输出 0 到 4
}

for-in 循环

var numbers = [1, 2, 3, 4, 5];
for (var number in numbers) {
  print(number);
}

forEach 循环

var fruits = ['苹果', '香蕉', '橙子'];
fruits.forEach((fruit) => print(fruit));

while 循环

while 循环

int count = 0;
while (count < 5) {
  print(count);
  count++;
}

do-while 循环

int num = 1;
do {
  print(num);
  num *= 2;
} while (num <= 16);

break 和 continue

break 语句

for (int i = 0; i < 10; i++) {
  if (i == 5) {
    break; // 跳出循环
  }
  print(i);
}

continue 语句

for (int i = 0; i < 5; i++) {
  if (i == 2) {
    continue; // 跳过当前迭代
  }
  print(i);
}

标签语句

outerLoop: for (int i = 0; i < 3; i++) {
  for (int j = 0; j < 3; j++) {
    if (i == 1 && j == 1) {
      break outerLoop; // 跳出外层循环
    }
    print("$i, $j");
  }
}

异常处理流程

try {
  int result = 12 ~/ 0; // 除以零异常
  print(result);
} on IntegerDivisionByZeroException {
  print("不能除以零");
} catch (e) {
  print("捕获到异常:$e");
} finally {
  print("总是执行");
}

assert 语句

在开发模式下进行断言:

int age = -5;
assert(age >= 0, "年龄不能为负数");

条件表达式

三元运算符

int number = 15;
String result = number % 2 == 0 ? "偶数" : "奇数";

?? 运算符

String? name;
String displayName = name ?? "匿名用户";

最佳实践

  1. 合理使用控制流语句,避免过度嵌套
  2. 优先使用 for-in 和 forEach 进行集合遍历
  3. 适当使用 break 和 continue 控制循环流程
  4. 注意异常处理的完整性
  5. 合理使用断言进行开发时的调试

实战案例:一个方法里的类型分发

ygking_json_to_dart_model 的 convertJsonToDart 入口,核心就是一段类型分发:

String convertJsonToDart(String jsonStr, String className) {
  try {
    final dynamic jsonData = json.decode(jsonStr);
    if (jsonData is Map<String, dynamic>) {
      _generateClass(jsonData, className, buffer, className);
    } else if (jsonData is List &&
        jsonData.isNotEmpty &&
        jsonData[0] is Map<String, dynamic>) {
      // 数组:取第一个元素当模板
      _generateClass(jsonData[0], className, buffer, className);
    } else {
      return '// 错误: JSON格式无效\n// 输入必须是对象或对象数组';
    }
    return buffer.toString();
  } catch (e) {
    return '// 错误: JSON格式无效\n// $e';
  }
}

这段 if-else if-else 有三个值得说的地方:

  1. 用 is 做类型分发,而不是 runtimeType ==。is 还顺带做了类型提升——进到第一个分支里,jsonData 就已经被编译器当成 Map<String, dynamic>,直接传给 _generateClass 不用强转。这是 Dart 控制流里最实用的特性之一。

  2. 条件里塞了业务规则:jsonData is List && jsonData.isNotEmpty && jsonData[0] is Map。空数组直接判无效——因为空数组没有结构信息,生成不出来类。控制流的条件应该表达业务语义,而不是单纯的类型检查。“是 List”不够,“是能生成类的 List”才够。

  3. else 分支返回错误注释,而不是抛异常。前面错误处理那篇讲过,这是工具场景的刻意选择。控制流和错误处理是一体的:else 在这里承担了”兜底”职责,保证方法所有路径都有返回值,调用方永远拿到一个 String。

总结

控制流语句本身都很简单,难的是条件里写什么:把业务语义塞进条件(“是能生成类的 List”而不是”是 List”),保证每个分支都有明确归宿,代码读起来就顺。配合 is 的类型提升,Dart 的类型分发写起来比多数语言都省事。


分享这篇文章:


相关文章

上一篇
Dart 异步编程详解
下一篇
Dart 运算符和表达式详解