这是代码示例: Try Throw New FirstException()Finally Throw New SecondException()End Try 我发现它只会抛出SecondException而FirstException就会消失. 我认为FirstException将在SecondException的InnerException属性中,但它
Try
Throw New FirstException()
Finally
Throw New SecondException()
End Try
我发现它只会抛出SecondException而FirstException就会消失.
我认为FirstException将在SecondException的InnerException属性中,但它似乎不是.
我没有被阻止,因为我真的不需要FirstException来显示,我只是对这种行为很感兴趣.
>有没有办法知道SecondException在第一次被抛出时
在上层抓住它?
>如果第一个异常真的被第二个异常覆盖,那么它是什么
原因?
>是否会以其他语言发生?这合乎逻辑吗?
在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方法显示可能在Try和Finally块中引发异常的代码模式. ExceptionTest2方法调用ExceptionTest并报告从中返回的异常. ExceptionDemo以这样的方式调用ExceptionTest2,以便在Try和Finally块的不同组合中引发异常.
如图所示,如果在清理期间发生异常,则该异常将返回给调用者,原始异常是其数据字典中的项.另一种模式是捕获清理时发生的异常并将其包含在原始异常的数据中(这将是未被捕获的).我的一般倾向是,在许多情况下传播清理期间发生的异常可能更好,因为任何计划处理原始异常的代码都可能期望清理成功;如果无法满足这样的期望,那么逃避的例外应该不是调用者所期望的那样.还要注意,后一种方法需要稍微不同的方法来向原始异常添加信息,因为嵌套的Try块中抛出的异常可能需要保存有关嵌套的Finally块中抛出的多个异常的信息.
