异常嵌套的异常消息

时间:2014-11-28 09:36:15

标签: c#

考虑我正在开发一个库。当这个库遇到异常时它无法自行处理(例如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:不在乎

来自评论:

  

不要浪费时间捕捉无法处理的异常。让来电者处理它。

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

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

请将此问题理解为:如果我有充分理由嵌套异常,我的消息应该如何?

讨论 if 您希望更好地嵌套异常属于here

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

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

此外,如果通过多个图层抛出异常,您的推理每个图层都会添加自己的包装,这意味着顶层必须向下钻取多个内部异常以获得实际错误 - 呃!

最高级别总是可以捕获并记录任何尚未处理的异常。

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

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

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