VB.NET尝试/捕获/何时 - 远离或有它的用途?

Lao*_*jin 6 vb.net exception-handling

与c#不同,VB.NET有条件地捕获Try/Catch/Finally块中的异常.

我以为我在某个地方读到这通常是不好的做法,因为它鼓励人们将(商业)逻辑放在处理机制的异常中,并且你最终会得到一个美化GoTo.

Try
     // Do something
Catch ex As MyException When [condition]
     // 
End Try
Run Code Online (Sandbox Code Playgroud)

那么是否有使用该When功能的合法案例或我们应该远离它?

这可能已经得到了解答,但我无法找到任何相关的,因为"当"是一个非常糟糕的搜索关键字.

Dam*_*ver 6

我能想到的通常情况是,您只想根据该异常的内容捕获特定异常.例如:

Try
     // Do something
Catch ex As SqlException When ex.Number = 547
     // Constraint Violation
End Try
Run Code Online (Sandbox Code Playgroud)

这样可以避免捕获所有 SqlException s,然后检查Number属性,然后在不匹配的情况下重新抛出异常.

另请参见异常过滤器的优缺点:

例如,如果你有一个相当普遍的异常,比如COMException,你通常只想在它代表某个HRESULT时捕获它.例如,当它表示E_FAIL时,你想让它变为unhanded,但是当它代表E_ACCESSDEINED时你想要捕获它,因为你有一个替代它的情况.在这里,这是一个完全合理的条件catch子句:

Catch ex As System.Runtime.InteropServices.COMException When ex.ErrorCode() = &H80070005 
Run Code Online (Sandbox Code Playgroud)

另一种方法是将条件放在catch块中,如果不符合您的条件,则重新抛出异常.例如:

Catch ex As System.Runtime.InteropServices.COMException 
    If (ex.ErrorCode != &H80070005) Then Throw 
Run Code Online (Sandbox Code Playgroud)

从逻辑上讲,这种"捕获/重新抛出"模式与过滤器的作用相同,但存在一个微妙而重要的区别.如果异常未处理,那么两者之间的程序状态就大不相同了.在catch/rethrow情况下,未处理的异常似乎来自catch块中的Throw语句.除此之外不会有任何调用堆栈,并且任何finally块到catch子句都将被执行.两者都使调试更加困难.在过滤器的情况下,异常从原始抛出点开始未处理,并且finally子句没有更改任何程序状态.