【问题标题】:Proper way to throw Errors in Dart在 Dart 中抛出错误的正确方法
【发布时间】:2019-08-20 23:00:34
【问题描述】:

Dart 提供了一个Error 类和一个Exception 类来抛出异常。为什么Error 构造函数不像Exception 构造函数那样接受消息参数?

来自Error class docs

程序失败时抛出的错误对象。

Error 对象表示程序员应该避免的程序故障。

来自Exception class docs

异常旨在向用户传达有关失败的信息,以便可以通过编程方式解决错误。它旨在被捕获,并且应该包含有用的数据字段。

较早的SO answer 引用了一篇文章来确认这种区别。

我喜欢这种区别。这告诉我,我的许多检查都应该抛出 Error 的实例。

我很高兴使用错误类型对Error 进行子类化,但我仍然需要报告导致错误的值。为什么 Dart 让我可以轻松地使用 Exception 而不是 Error

我意识到我可以通过声明一个应用范围的错误类来解决问题:

class AppError extends Error {
  String message;

  AppError([this.message]);

  String toString() {
    return message == null ? runtimeType : "$runtimeType: $message";
  }
}

ErrorException 之间的这种差异让我认为我误解了Error 或使用不当。在 Dart 中抛出非用户错误的正确方法是什么?

【问题讨论】:

  • 可能是直接使用 Error 来劝阻(你可能不应该这样做)。考虑通过assert(condition, message)StateError 改用AssertionError
  • @jamesdlin,啊哈!我打赌就是这样。非常感谢!
  • Google 显示 'dart "throw StateError"' 总共有 42 个命中,这并没有给我太多信心,但这个示例页面是其中之一,表明 StateError 确实是可以使用的throwable。 (assert() 使用有限,因为它无法保护生产中的状态。)dart.dev/samples#exceptions
  • 在发布代码中关于assert() 的公平点,尽管您可以直接抛出AssertionError(或创建自己的assert 类似函数来执行此操作)。关于StateError,低命中数可能会产生误导,因为StateError 经常通过其他机制(例如quiver.check 函数)抛出。
  • @jamesdlin,如果您将两个 cmets 组合成一个答案,我很乐意将其标记为我的首选答案。

标签: exception dart error-handling


【解决方案1】:

如果有的话,Exception 接收消息是一个错误。你应该永远抛出一个普通的new Exception("message")

ErrorException(或者实际上是任何非Error 抛出的对象)之间的区别在于Error 表示编程失败。

您的程序不应将Error 作为正常操作的一部分。您不应该捕获特定的Error 并对其做出反应。 (框架可以捕获所有抛出的对象并记录它们,以便继续运行,但它们不应该专门对单个错误做出反应)。 这意味着您使用哪个类来表示错误实际上并不重要。错误的唯一目的是向程序员显示,以便他们修复错误。 Dart 有许多有用的 Error 子类,它们涵盖了大多数情况,并确保错误消息的格式一致。没有什么本质上要求您使用 RangeError 来处理越界错误,它只是一个非常方便的帮助类,它可以帮助读者了解发生了什么,我们建议您使用它。

当函数的参数不满足它的额外(非类型)要求(例如,列表必须非空)时,使用ArgumentError。 对于数字参数,当数字不在预期范围内时,有一个 RangeError。对于用作索引的数字(如list.operator[] 参数),甚至还有专门的IndexError。它们都是为了确保您收到一致的错误消息。

如果操作无法现在执行,因为对象不处于支持它的状态,请使用StateError

如果当前对象永远无法执行操作,请使用UnsupportedError

在实践中,StateErrorUnsupportedErrorArgumentError(及其子类)涵盖了用户代码引发的绝大多数运行时错误。 简单地抛出一个Error("message") 比使用其中之一提供的信息更少,并且发明一种新的错误类型很少值得。

另一方面,异常打算被捕获和处理。 它是给调用者的消息,与返回值具有相同的重要性,它应该包含足够的信息,以便调用者捕获函数可能抛出的特定记录异常,并且 对特定的异常情况做出反应。 这就是为什么一个异常至少应该有一个独特的类型,让你可以专门识别和捕获它,并且如果可能的话,它应该包含处理异常情况所需的任何信息。

FormatException 为例,它由各种parse 函数抛出。 它是特定于操作的。它包含可帮助您找出问题所在的可用信息(输入和与错误相关的位置,主要用于向用户显示,因为您无法修复输入。)

【讨论】:

  • 谢谢。我还有一个问题:in the documentation,我们可以看到代码:throw("some arbitrary error");。只扔一个字符串是一种不好的做法吗?这是否意味着有某种魔法将String 包裹在Exception 中?
  • 不,有 no 魔法可以包裹任何东西。你可以扔字符串。和整数。除了null 之外的任何对象都可以抛出,但是由于String 不是Error,所以抛出一个不利于报告错误,并且由于它不代表特定的异常情况,所以抛出一个不利于报告异常。所以,不要扔字符串。
【解决方案2】:

https://github.com/dart-lang/sdk/blob/master/sdk/lib/core/errors.dart

Dart 有几个可以立即使用的预定义错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-18
    • 1970-01-01
    • 2022-06-16
    • 1970-01-01
    • 2019-01-03
    • 1970-01-01
    • 2022-12-10
    • 2017-11-13
    相关资源
    最近更新 更多