Dart中推荐的方法是:断言或引发错误

时间:2019-09-07 11:49:54

标签: flutter dart

Dart明确区分了Error(在您的代码逻辑中表示一个问题且永远不会发生且永不被捕获)和Exception(在运行时数据基础上表示一个问题)之间。

我真的很喜欢这种区别,但是我想知道何时应该使用断言?

4 个答案:

答案 0 :(得分:3)

由于asserts在生产模式下会被忽略,因此您应该使用它们作为在调试模式下对代码逻辑进行初始测试的方式:

  

在生产代码中,断言将被忽略,并且不会评估断言的参数。

答案 1 :(得分:3)

背景

  • 在Dart中,Exception表示可能在运行时发生的预期不良状态。因为这些异常是预料之中的,所以您应该捕获它们并适当地对其进行处理。
  • 另一方面,Error适用于正在使用您的代码的开发人员。您抛出一个错误以使他们知道他们使用了错误的代码。作为使用API​​的开发人员,您不应捕获错误。您应该让他们让您的应用崩溃。让崩溃向您传达信息,您需要找出自己在做错什么。
  • assertError类似,因为它用于报告不应发生的不良状态。区别在于断言仅在调试模式下检查。在生产模式下,它们将被完全忽略。

详细了解ExceptionError here之间的区别。

接下来,这是一些示例,以查看Flutter源代码中如何使用它们。

引发异常的示例

这来自platform_channel.dart in the Flutter repo

@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;
}

这里的MissingPluginException是可能发生的计划中的不良状态。如果发生这种情况,平台通道API的用户需要准备好进行处理。

抛出错误的示例

这来自artifacts.dart in the flutter_tools repo

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.');
}

首先,穷尽所有可能性,然后引发错误。理论上这是不可能的。但是,如果抛出该错误,则可能是向API用户表示您使用错误,或者是向API维护人员表明他们需要处理另一种情况。

使用断言的示例

这来自overlay.dart in the Flutter repo

OverlayEntry({
  @required this.builder,
  bool opaque = false,
  bool maintainState = false,
}) : assert(builder != null),
      assert(opaque != null),
      assert(maintainState != null),
      _opaque = opaque,
      _maintainState = maintainState;

Flutter源代码中的模式是在构造函数的初始化列表中自由使用断言。它们比错误更常见。

摘要

当我阅读Flutter的源代码时,将asserts用作构造函数初始化器列表中的初步检查,并将错误作为方法主体中的最后检查。当然,就我所知,这并不是一个硬性规定,但似乎符合我到目前为止所看到的模式。

答案 2 :(得分:2)

Asserts是仅在开发中执行代码而又不影响发布模式性能的方法-通常是为了防止类型系统中缺少功能而导致的错误状态。

例如,只有断言可用于进行防御性编程 并提供const构造函数。

我们可以做到:

class Foo {
  const Foo(): assert(false);
}

但不能:

class Foo {
  const Foo() { throw 42; }
}

类似地,一些健全性检查相对昂贵。

例如,在Flutter的上下文中,您可能想遍历小部件树以检查小部件祖先上的某些内容。但这是昂贵的,因为这仅对开发人员有用。

在assert中进行检查可以同时实现发行版的性能和开发的实用性。

assert(someVeryExpensiveCheck());

答案 3 :(得分:1)

什么时候断言确切起作用?这取决于您使用的工具和框架:

Flutter在调试模式下启用断言。
默认情况下,仅开发工具(例如dartdevc)默认启用断言。
某些工具(例如dart和dart2js)通过以下命令行标志支持断言:--enable-asserts。
在生产代码中,断言会被忽略,并且不会评估断言的参数。

引用:https://dart.dev/guides/language/language-tour#assert