-->

在try / finally块双人异常抛出(Double exception throwing in

2019-09-23 04:35发布

下面的代码示例:

Try
    Throw New FirstException()
Finally
    Throw New SecondException()
End Try

我想通了,它只是抛出SecondException并FirstException刚刚消失。

我想FirstException会SecondException的InnerException属性里面,但似乎事实并非如此。

我不会阻止任何东西,因为我并不真正需要的FirstException展现出来,我只是好奇,而有关此问题。

  • 有没有办法知道SecondException在上层追赶,当这一切都先被抛出?

  • 如果第一个例外真的被第二重写,是什么原因?

  • 它是否在所有其他语言的发生呢? 它是合理的?

Answer 1:

唯一的例外在.net中处理的限制是没有很好的方法代码在Finally阻止知道什么异常,如果有的话,引起了代码Try块退出,也没有对代码在任何正常的方式finally块里面确实有这样的信息,以使其可用于代码可能会抛出异常。

在vb.net中,有可能在未完善的作品相当不错的方式的东西,即使它看起来有点丑。

Module ExceptionDemo
    Function CopySecondArgToFirstAndReturnFalse(Of T)(ByRef dest As T, src As T) As Boolean
        dest = src
        Return False
    End Function
    Function AnnotateExceptionAndReturnFalse(ex As Exception, TryBlockException As Exception) As Boolean
        If ex Is Nothing Then Return False ' Should never occur
        If TryBlockException Is Nothing Then Return False ' No annotation is required
        ex.Data("TryBlockException") = TryBlockException
        Return False
    End Function

    Sub ExceptionTest(MainAction As Action, CleanupAction As Action)
        Dim TryBlockException As Exception = Nothing
        Try
            MainAction()
        Catch ex As Exception When CopySecondArgToFirstAndReturnFalse(TryBlockException, ex)
            ' This block never executes, but above grabs a ref to any exception that occurs
        Finally
            Try
                CleanupAction()
            Catch ex As Exception When AnnotateExceptionAndReturnFalse(ex, TryBlockException)
                ' This block never executes, but above performs necessary annotations
            End Try
        End Try
    End Sub

    Sub ExceptionTest2(Message As String, MainAction As Action, CleanupAction As Action)
        Debug.Print("Exception test: {0}", Message)
        Try
            ExceptionTest(MainAction, CleanupAction)
        Catch ex As Exception
            Dim TryBlockException As Exception = Nothing
            Debug.Print("Exception occurred:{0}", ex.ToString)
            If ex.Data.Contains("TryBlockException") Then TryBlockException = TryCast(ex.Data("TryBlockException"), Exception)
            If TryBlockException IsNot Nothing Then Debug.Print("TryBlockException was:{0}", TryBlockException.ToString)
        End Try
        Debug.Print("End test: {0}", Message)
    End Sub
    Sub ExceptionDemo()
        Dim SuccessfulAction As Action = Sub()
                                             Debug.Print("Successful action")
                                         End Sub
        Dim SuccessfulCleanup As Action = Sub()
                                              Debug.Print("Cleanup is successful")
                                          End Sub
        Dim ThrowingAction As Action = Sub()
                                           Debug.Print("Throwing in action")
                                           Throw New InvalidOperationException("Can't make two plus two equal seven")
                                       End Sub
        Dim ThrowingCleanup As Action = Sub()
                                            Debug.Print("Throwing in cleanup")
                                            Throw New ArgumentException("That's not an argument--that's just contradiction")
                                        End Sub
        ExceptionTest2("Non-exception case", SuccessfulAction, SuccessfulCleanup)
        ExceptionTest2("Exception in main; none in cleanup", ThrowingAction, SuccessfulCleanup)
        ExceptionTest2("Exception in cleanup only", SuccessfulAction, ThrowingCleanup)
        ExceptionTest2("Exception in main and cleanup", ThrowingAction, ThrowingCleanup)
    End Sub
End Module

该模块上面几个助手模块,这大概应该是在自己的“异常助手”模块开始。 该ExceptionTest方法显示其可能在这两个抛出异常的代码模式TryFinally块。 该ExceptionTest2方法调用ExceptionTest和报告什么异常,如果任何来自回来。 ExceptionDemo以这样的方式来引起不同的组合异常调用ExceptionTest2 TryFinally的块。

如图所示,如果清理期间发生异常,该异常将被返回给调用者,与原来的例外是在其一个项目Data字典。 一个替代图案将赶上上清理发生异常并将其包括在原始异常(这将留下未捕获的)的数据。 我总的倾向是,它可能在许多情况下,更好地传播该清理过程中发生异常,因为这是计划来处理原始异常可能会想到的是清除任何成功的代码; 如果这样的期望不能得到满足,逃逸的例外可能不应该是一个呼叫者期待。 还要注意的是,后一种方法需要将信息添加到原始异常的方法稍有不同,因为这是在嵌套抛出的异常Try块可能需要按住约嵌套被抛出该多个异常信息的Finally块。



Answer 2:

我猜为什么这样工作的主要解释是,你永远不会赶上你的第一种例外情形,并且在传递链。 如果你有一个像上面的一个情况下,你可以在路上扔几个例外回原来的调用者,那么你必须要么赶上他们,因为他们被抛出(并创造下一个时,它们作为内部异常):

Dim ex1 As Exception = Nothing
Try
    Throw New Exception("first exception")
Catch ex As Exception
    ex1 = ex
Finally
    Throw New Exception("second exception", ex1)
End Try

或者,可能会更好 - 只是不扔,直到你把所有的异常想通了:

Dim ex1 As Exception = Nothing
Try
    ex1 = New Exception("first exception")
Finally
    Throw New Exception("second exception", ex1)
End Try

抛出和捕获异常昂贵,所以它可能是最好不要扔,直到你准备返回,只是沿途记录。



文章来源: Double exception throwing in a try / finally block