控制语句

你可以在 Dart 中使用下面任意方式控制代码的执行流程:

  • ifelse
  • for 循环
  • whiledo-while 循环
  • breakcontinue
  • switchcase
  • 断言

你也可以使用 try-catchthrow 控制流程

If 和 else

Dart 支持带 else 语句的 if 语句,如下面例子所展示的。

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

不像 JavaScript,条件必须使用布尔值,而不是其他的。

For 循环

你可以使用标准的 for 循环进行迭代。比如:

var message = StringBuffer('Dart is fun'); for (var i = 0; i < 5; i++) { message.write('!'); }

Dart for 循环中的闭包会捕获 index 的,避免 JavaScript 中常见的一个坑。比如,考虑:

var callbacks = []; for (var i = 0; i < 2; i++) { callbacks.add(() => print(i)); } callbacks.forEach((c) => c());

输出是 0 然后是 1,如期望一样。对比下来,在 JavaScript 中上面的例子会输出 22

如果你要迭代的对象是一个 Iterable,你可以使用 forEach() 方法。如果你不需要知道当前迭代的计数,使用 forEach() 是一个不错的选择。

candidates.forEach((candidate) => candidate.interview());

像列表和集合这样的 Iterable 也支持 for-in 形式的 迭代

var collection = [0, 1, 2]; for (var x in collection) { print(x); // 0 1 2 }

While 和 do-while 循环

While 循环在循环之前计算条件:

while (!isDone()) { doSomething(); }

do-while 循环在循环后计算条件:

do { printLine(); } while (!atEndOfPage());

Break 和 continue

使用 break 中止循环:

while (true) { if (shutDownRequested()) break; processIncomingRequests(); }

使用 continue 跳到下一个循环:

for (int i = 0; i < candidates.length; i++) { var candidate = candidates[i]; if (candidate.yearsExperience < 5) { continue; } candidate.interview(); }

如果你在用 Iterable,比如列表或者集合,你可能会以不同的方式编写上面的例子:

candidates .where((c) => c.yearsExperience >= 5) .forEach((c) => c.interview());

Switch 和 case

Dart 中的 switch 语句使用 == 比较整数、字符串或其他编译期常量。被比较的对象必须全部是相同的类的实例(而不是它的任何子类),而且该类必须不能重载 ==枚举类switch 语句中可以良好地运行。

说明:Dart 中的 switch 语句只适用于有限的情况,就像翻译员和扫描仪。

作为规定,每一个非空的 case 子句都以 break 结束。结束一个非空 case 子句的其他方式是 continuethrow 或者 return 语句。

在没有条件匹配的情况下,使用 default 字句执行代码:

var command = 'OPEN'; switch (command) { case 'CLOSED': executeClosed(); break; case 'PENDING': executePending(); break; case 'APPROVED': executeApproved(); break; case 'DENIED': executeDenied(); break; case 'OPEN': executeOpen(); break; default: executeUnknown(); }

下面的例子遗漏了 case 子句中的 break,这会产生一个错误:

var command = 'OPEN'; switch (command) { case 'OPEN': executeOpen(); // 错误:缺少 break case 'CLOSED': executeClosed(); break; }

然而,Dart 确实支持空的 case 子句,来允许 fall-through 形式:

var command = 'CLOSED'; switch (command) { case 'CLOSED': // 空子句 fall-through case 'NOW_CLOSED': // CLOSED 和 NOW_CLOSED 都会执行 executeNowClosed(); break; }

如果你真的想 fall-through,你可以使用 continue 语句并加上一个标签:

var command = 'CLOSED'; switch (command) { case 'CLOSED': executeClosed(); continue nowClosed; // 在 nowClosed 标签处继续执行 nowClosed: case 'NOW_CLOSED': // CLOSED 和 NOW_CLOSED 都会执行 executeNowClosed(); break; }

一个 case 子句可以有局部变量,这些变量仅在该子句中可见。

断言

在开发时,如果一个布尔值为 false,使用 断言 语句——assert(condition, optionalMessage)——来中止正常的执行。你可以在本教程中找到断言语句的例子。下面就是一些:

// 确保变量是非空的值 assert(text != null); // 确保变量小于100 assert(number < 100); // 确保变量是一个 https 的 URL assert(urlString.startsWith('https'));

要添加信息到一个断言,使用一个字符串作为 assert 的第二个参数。

assert(urlString.startsWith('https'), 'URL ($urlString) should start with "https".');

传递给 assert 的第一个参数只能是可解析为布尔值的表达式。如果这个表达式的值是 true,断言成功并且继续执行。如果它是 false,断言失败并且抛出一个异常(一个 AssertionError)。

断言到底何时起作用?这取决于你所使用的工具和框架:

  • Flutter 在调试模式下启动断言。
  • 开发专用工具像是 dartdevc 通常默认支持断言。
  • 还有一些工具,像是 dart 和 dart2js,通过命令行标志来支持断言:--enable-asserts

在生产环境的代码中,断言会被忽略,而且 assert 的参数也不会被求值。