为什么要捕获异常然后再次抛出它?

问题描述 投票:0回答:10

在网络服务中我看到以下代码:

<WebMethod()> _
Public Function dosomething() As Boolean
    Try
        If successful Then
            Return True
        Else
            Return False
        End If
    Catch ex As Exception
        Throw ex
    End Try
End Function

捕获异常并再次抛出它有什么意义?我错过了什么吗?

编辑: 感谢您的回答!我认为是这样的,但不确定我是否可以/会在没有任何影响的情况下重构它们。

vb.net web-services exception
10个回答
47
投票

不要这样做。

如果您绝对需要重新抛出异常,只需使用

throw;
使用
throw ex;
会擦除堆栈跟踪,这是绝对错误的。


15
投票

我想不出有什么理由为了功能而这样做。但是,如果之前删除了一些错误处理(通常是日志记录),并且开发人员删除了日志处理但没有重组代码以删除多余的 try/catch,则可能会出现这种情况。


5
投票

可能是调试留下的一些代码(您可以在抛出时设置断点,以便可以在调试器中检查异常)。 如果我想记录异常然后将其传递到链上,我可能会这样做,尽管我可能会用更有意义的(对我的应用程序)错误消息将异常包装在另一个异常中。


5
投票

其中一个架构(设计模式)我可以看到它用于处理事务的地方。该函数完成其工作,失败,catch 块将事务完成到已知状态(通常是回滚),然后抛出用户定义的异常。

就目前而言,将该代码重构为更理智的状态。


1
投票

不仅 try/catch 没有意义,IF 也没有意义。整个函数可以缩减为一行:

return successful

到了这个时候,何必再烦恼呢?为什么不直接测试“成功”而不是调用函数呢?

好吧,这是一个 Web 方法,我想您需要该函数只是为了给 Ajax 或任何人一个句柄。

(是的,我知道我的答案迟了7年。我只是在搜索完全不相关的东西时偶然发现了这个。)


1
投票

来自微软的代码分析:(CA2200:重新抛出以保留堆栈详细信息)

“一旦抛出异常,它携带的部分信息就是堆栈跟踪。堆栈跟踪是方法调用层次结构的列表,从抛出异常的方法开始,到捕获异常的方法结束。如果通过在 throw 语句中指定异常来重新引发异常,堆栈跟踪将在当前方法处重新启动,并且抛出异常的原始方法和当前方法之间的方法调用列表将丢失,以保留原始堆栈。带有异常的跟踪信息,使用 throw 语句而不指定异常。”

  Sub CatchAndRethrowImplicitly()
     Try
        ThrowException()
     Catch e As ArithmeticException
        ' Satisfies the rule.
        Throw
     End Try
  End Sub

https://learn.microsoft.com/en-us/visualstudio/code-quality/ca2200-rethrow-to-preserve-stack-details?view=vs-2019


0
投票

Monitor 的模式使得这很可能重新抛出错误,因为您需要一个finally 来确保调用 Monitor.Exit

https://msdn.microsoft.com/en-us/library/4tssbxcw(v=vs.110).aspx

Dim lockObj As New Object()

If Monitor.TryEnter(lockObj) Then
    Try
        ' The critical section.
    Catch
       throw
    Finally
       ' Ensure that the lock is released.
       Monitor.Exit(lockObj)
    End Try
End If

0
投票

这样做有非常充分的理由,特别是在全栈/N 层环境中。

尝试/捕获类库中的代码、记录异常并将其扔回调用应用程序以允许调用者按照其想要的方式处理异常是有意义的。

请记住,在全栈环境中,堆栈应该是独立的,并且不知道彼此的内部功能,同样,它们不应该假设知道堆栈在其自身之外如何处理捕获的异常。 实时处理异常然后将其传递给调用者是一件非常有帮助的事情。

并且始终只使用“Throw”,而不是“Throw ex”。 抛出将重新抛出句柄异常,保持其堆栈完整。


0
投票

我使用(重新)抛出来允许我的公司数据库库在错误时回滚事务,同时仍然向调用程序提供完整的错误信息。


-9
投票

如果您想捕获除异常的子类之外的异常,您可能需要这样做。

例如,

try {
    // Something stupid
}
catch(RuntimeException e) {
    throw e; //Handle it outside
}
catch (Exception e) {
    // I'm dead
}
© www.soinside.com 2019 - 2024. All rights reserved.