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

Tho*_*mas 6 dart flutter

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)


Sur*_*gch 9

背景

  • 在 Dart 中,anException用于可能在运行时发生的预期不良状态。因为这些异常是预料之中的,所以您应该捕获它们并适当地处理它们。
  • Error,在另一方面,是谁在使用你的代码的开发人员。你抛出一个错误让他们知道他们使用你的代码是错误的。作为使用 API 的开发人员,您不应该捕获错误。你应该让他们让你的应用程序崩溃。让崩溃成为一个信息,告诉你你需要去找出你做错了什么。
  • Anassert与 an 相似Error,因为它用于报告不应该发生的不良状态。不同之处在于断言仅在调试模式下检查。它们在生产模式下完全被忽略。

了解更多关于的区别ExceptionError 这里

接下来,这里有几个例子,看看每个例子是如何在 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 源代码时,在构造函数初始值设定项列表中使用断言作为初步检查,并在方法体中作为最后手段检查抛出错误。当然,据我所知,这并不是一个硬性规定,但它似乎符合我目前所看到的模式。


Maz*_*him 5

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

\n\n
\n

在生产代码中,断言将被忽略,并且断言的参数将被评估\xe2\x80\x99。

\n
\n