【问题标题】:Rethrowing an exception from an exception catch从异常捕获中重新抛出异常
【发布时间】:2011-06-27 04:08:30
【问题描述】:

捕获一个异常然后抛出另一个异常是个好主意吗?

像这样:

Try
    ' Do operation xxx
Catch ex As Exception
    ' Operation xxx failed, need to execute cleanup
    ' But now I've caught this exception outside of my main control logic, 
    ' so I would like to re-throw it
    Throw New ApplicationException("XXX failed")
End Try

这样做的原因是,虽然我在更高级别的逻辑上捕获了我的异常(以确保我可以正确记录它),但我需要在异常事件中执行一些我只能在我的内部执行的操作类/函数。

你能想出什么原因/场景说明这是个坏主意吗?

【问题讨论】:

  • 你失去了原来的堆栈跟踪抛出这样的

标签: .net vb.net exception-handling


【解决方案1】:

几点。首先,我同意 John Saunders 关于使用 finally 的观点。你真的应该在那里做你的清理工作。

其次,如果你想抛出一个新的异常,那么要么抛出一个异常,要么根据Exception创建你自己的异常类型。如果您正在捕获 I/O 或 SQL 等低级异常,并且想要重新抛出特定于正在执行的操作的某些内容,我建议您这样做。在这种情况下,您可能希望将捕获的异常嵌套为 InnerException。寻找构造函数重载来轻松完成此操作。

第三,如果你只想重新抛出,我相信你可以只写“抛出”,它隐式地抛出当前捕获的异常。至少在 C# 中是这样的,它允许异常及其整个堆栈跟踪和其他数据继续完整地在堆栈中冒泡。

【讨论】:

  • 我建议不要创建自定义异常,除非某些调用者实际上会捕获自定义异常。
  • @John,我认为它假设会是这样,对吧?为什么要创建自定义异常,除非它们打算用于 catch 条件逻辑中使用的类型?
  • 许多人(可能来自旧文档)认为他们应该无缘无故地创建新的异常;主要是因为它们抛出不同类型的异常,并且没有考虑到没有人足够关心它们以明确地捕获它们。
  • @John,我同意没有充分的理由无缘无故地创建额外的异常类。但是,如果他们正在传达不同的错误条件,那么我认为我们可能同意该技术非常有用。我目前在一个非常庞大、复杂的软件系统上工作,该系统使用大约 15 种异常类型,每种异常类型都有 10 到 50 个与之关联的键/消息对,以获得进一步的粒度,并且它们都用于条件逻辑。如果我正在编写一个公共 API 并想要一个非常有用、丰富的接口,那么我唯一能看到的变得非常富有的情况。
【解决方案2】:

这不一定是个坏主意。如果一个特定的异常对你的方法的调用者没有意义,因为它与调用者不知道的低级细节有关,那么最好将异常包装在一个新的异常中,解释什么是调用者做错了。

我还想补充一点,在 99% 的情况下,您应该捕获特定异常,而不是一般的 Exception 类型。如果您捕获所有异常,您很可能会隐藏您不准备处理的故障。最好让你的程序崩溃并告诉你出了什么问题,让你想知道为什么你的程序不能正常工作。

【讨论】:

  • 但是当他换行时,他需要包含内部异常。
【解决方案3】:

是的,这是个坏主意。

首先,不要为了执行清理而捕获异常。为此使用 finally 块,因为无论是否发生异常都会执行它。你也不需要抛出一个新的异常只是说“XXX失败”。堆栈跟踪将显示这一点。

其次,不要使用ApplicationException。 Microsoft 曾经建议用户定义的异常从ApplicationException 派生,但结果证明这是一个坏主意。他们现在建议我们只使用Exception

最后,当您因为旧异常而要抛出新异常时,请务必包含旧异常:

Throw New Exception("My new message", ex)

【讨论】:

  • @Robert:是的,但他似乎认为他需要一条新消息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-24
  • 2010-10-03
  • 2016-02-17
  • 2020-02-13
  • 2021-04-01
  • 2014-08-18
  • 2013-10-04
相关资源
最近更新 更多