Dart明确区分了Error和Exception,它们是代码逻辑中的一个问题,该错误永远不会发生,也永远不会被捕获,这是基于运行时数据的一个信号。
我真的很喜欢这种区别,但是我想知道何时应该使用断言?
Rém*_*let 13
断言是执行仅在开发中有用的代码的方法,而不会妨碍发布模式的性能——通常是为了防止由于类型系统中缺少功能而导致的不良状态。
例如,只有断言可用于进行防御性编程并提供 const 构造函数。
我们可以做的:
class Foo {
const Foo(): assert(false);
}
Run Code Online (Sandbox Code Playgroud)
但不能这样做:
class Foo {
const Foo() { throw 42; }
}
Run Code Online (Sandbox Code Playgroud)
同样,一些健全性检查相对昂贵。
例如,在 Flutter 的上下文中,您可能想要遍历小部件树以检查小部件的祖先上的某些内容。但这是昂贵的,因为某些东西只对开发人员有用。
在断言中进行检查既可以提高发布性能,也可以提高开发效率。
assert(someVeryExpensiveCheck());
Run Code Online (Sandbox Code Playgroud)
Exception用于可能在运行时发生的预期不良状态。因为这些异常是预料之中的,所以您应该捕获它们并适当地处理它们。Error,在另一方面,是谁在使用你的代码的开发人员。你抛出一个错误让他们知道他们使用你的代码是错误的。作为使用 API 的开发人员,您不应该捕获错误。你应该让他们让你的应用程序崩溃。让崩溃成为一个信息,告诉你你需要去找出你做错了什么。assert与 an 相似Error,因为它用于报告不应该发生的不良状态。不同之处在于断言仅在调试模式下检查。它们在生产模式下完全被忽略。了解更多关于的区别Exception和Error 这里。
接下来,这里有几个例子,看看每个例子是如何在 Flutter 源代码中使用的。
这来自Flutter repo 中的 platform_channel.dart:
@optionalTypeArgs
Future<T?> _invokeMethod<T>(String method, { required bool missingOk, dynamic arguments }) async {
assert(method != null);
final ByteData? result = await binaryMessenger.send(
name,
codec.encodeMethodCall(MethodCall(method, arguments)),
);
if (result == null) {
if (missingOk) {
return null;
}
throw MissingPluginException('No implementation found for method $method on channel $name');
}
return codec.decodeEnvelope(result) as T;
}
Run Code Online (Sandbox Code Playgroud)
这MissingPluginException是可能发生的有计划的不良状态。如果发生这种情况,平台通道 API 的用户需要做好处理的准备。
这来自flutter_tools repo 中的 artifacts.dart。
TargetPlatform _currentHostPlatform(Platform platform) {
if (platform.isMacOS) {
return TargetPlatform.darwin_x64;
}
if (platform.isLinux) {
return TargetPlatform.linux_x64;
}
if (platform.isWindows) {
return TargetPlatform.windows_x64;
}
throw UnimplementedError('Host OS not supported.');
}
Run Code Online (Sandbox Code Playgroud)
首先用尽所有可能性,然后抛出错误。这在理论上应该是不可能的。但是如果它被抛出,那么它要么向 API 用户表明您使用它是错误的,要么向 API 维护者表明他们需要处理另一种情况。
这来自Flutter repo 中的 overlay.dart:
OverlayEntry({
required this.builder,
bool opaque = false,
bool maintainState = false,
}) : assert(builder != null),
assert(opaque != null),
assert(maintainState != null),
_opaque = opaque,
_maintainState = maintainState;
Run Code Online (Sandbox Code Playgroud)
Flutter 源代码中的模式是在构造函数的初始化列表中大量使用断言。它们比错误更常见。
当我阅读 Flutter 源代码时,在构造函数初始值设定项列表中使用断言作为初步检查,并在方法体中作为最后手段检查抛出错误。当然,据我所知,这并不是一个硬性规定,但它似乎符合我目前所看到的模式。
| 归档时间: |
|
| 查看次数: |
104 次 |
| 最近记录: |