【问题标题】:Exception messages for exception nesting [closed]异常嵌套的异常消息[关闭]
【发布时间】:2014-11-28 21:04:48
【问题描述】:

假设我正在开发一个库。当此库遇到无法自行处理的异常时(例如WebException),它将包装该异常以向客户端隐藏实现细节,并为它们提供统一的异常处理方式。

关于此类异常的信息,最佳实践/指南/注意事项/注意事项是什么?

选项 1:包装器不包含任何内容

我个人最喜欢的,每个异常都对自己的消息负责。包装器使用的措辞比预期的内部异常更通用。

try
{
  // ...
}
catch (WebException ex)
{
  throw new MyLibraryException("An error occured accessing a web ressource", ex);
}

选项 2:显示内部消息

除了内在异常要说的话,你还能说什么?不确定这是否可行...

try
{
  // ...
}
catch (WebException ex)
{
  throw new MyLibraryException(ex.Message, ex);
}

选项 3:连接它

我不认为这是一个好主意,但它是在我们在本地进行的一次讨论中提出的,所以我想将其作为一个选项提出。

外部异常将负责连接内部异常消息。

try
{
  // ...
}
catch (WebException ex)
{
  string message = string.Format("An error occured accessing a web ressource: {0}", ex.Message);
  throw new MyLibraryException(message, ex);
}

我觉得必须有关于该主题的明确指南(例如 MSDN),但我无法找到它们。我已经检查了Best Practices for Exceptions,但无济于事。

选项 4:不关心

来自cmets:

不要浪费时间去捕捉你无法处理的异常。让调用者处理。

我认为这个选项不可行,因为虽然我自己无法处理异常,但我知道它可能会发生并且我想对调用者隐藏细节(​​例如要处理哪种异常类型?)。这很重要,因为有一天我可以切换到另一个为我提供 Web 访问的框架,因此例外情况可能会改变。包装有助于维护抽象(恕我直言)。

编辑:似乎有很多混乱。 我不打算将此模式应用于每个例外情况。我通常会忽略或重新抛出 (throw;) 异常,例如 FileNotFoundException 和许多其他核心框架异常。但是,在某些情况下我想隐藏,我应该如何以最好的方式做到这一点?

将此问题解读为:如果我有充分的理由嵌套异常,我的消息应该是什么样子?

关于如果你想嵌套异常最好属于here的讨论。

【问题讨论】:

  • 选项 4:不要浪费时间去捕捉你无法处理的异常。让调用者处理。
  • WPF 使用选项 3,这很痛苦。我真的很想直接查看内部异常(选项 4)。
  • 如果你知道它可能会发生,也许你应该处理它,并从你的方法中返回false 或类似的东西,而不是让异常冒泡。从您链接的最佳实践文章中:“精心设计的应用程序可以处理异常和错误以防止应用程序崩溃。”简单地将一个异常替换为另一个异常,您并没有处理或防止崩溃。
  • 如果您觉得自定义异常有意义(例如,您希望 API 的用户能够捕捉到特定的错误类型,或者可能没有合适的异常类已经在框架中),那么我会推荐选项#1。
  • 关于何时创建自定义异常的很好的讨论可以在这里找到:stackoverflow.com/questions/3443570/…

标签: c#


【解决方案1】:

如果您需要大量日志记录,明智的做法是捕获链上的错误,以便能够在日志消息中提供尽可能多的有关错误的详细信息。登录后,您应该重新抛出异常。确保使用throw; 而不是throw ex; 来保留堆栈跟踪。

【讨论】:

    【解决方案2】:

    选项 4:不要浪费时间来捕捉您无法处理的异常。让调用者处理它。调用者是否捕获 MyLibraryException 或 WebException 真的很重要吗?如果调用者可以处理并从 WebExceptions 中恢复,那么他们将想要捕获它,而不是您的 MyLibraryException。

    此外,如果异常是通过多个层抛出的,根据您的推理,每一层都会添加自己的包装,这意味着顶层必须深入研究多个内部异常才能找到实际错误 - 啊!

    最顶层总是可以有一个 catch all 来捕获和记录任何尚未处理的异常。

    最后,您应该记录您的库或它调用的代码可能会抛出哪些(基础)异常。

    编辑:关于抽象:抽象 MyLibraryException 中的异常对调用者没有帮助 - 他们无法在不知道最终原因的情况下从 MyLibraryException 中恢复,这是您包装的异常,因此您最好不要费心将其包装在放在第一位,让调用者直接接住。如果调用者无法从最终异常中恢复,那么他们可能会捕获所有内容并记录发生错误的事实,然后可能会终止应用程序。

    一个具体的例子:由于缺少文件,您的库中发生了 FileIOException。当然,最好将它扔给调用者以便他们可以从中恢复(也许用户忘记了关键文件),而不是调用者必须解释您的 MyLibraryException?

    【讨论】:

    • 我试图澄清我的意图。我并不总是应用这种模式。 IOExceptions 和 FileNotFound 是我通常会原封不动地传递的很好的异常示例。但是有一些合理的情况(毕竟:内部异常不是我编造的),我想尽可能好地处理它们。
    • 所以现在你可以随意包装哪些异常以及允许哪些异常。也许在某些情况下您让 IOExceptions 通过,有时您不会。来电者是如何知道这一切的?使用内部异常的库通常更接近于金属。
    • 假设我清楚地记录了这一点。当问一个问题时,我必须平衡过多的细节和抽象。老实说,我不明白为什么没有人打算回答我提出的问题:关于嵌套异常的错误消息的最佳实践是什么?并且:有指导方针吗?我没有问我是否应该嵌套异常。
    猜你喜欢
    • 1970-01-01
    • 2018-10-29
    • 2017-07-18
    • 1970-01-01
    • 2012-02-20
    • 2014-06-10
    • 2019-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多