6

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

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

Try
     // Do something
Catch ex As MyException When [condition]
     // 
End Try

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

这可能已经得到解答,但由于“何时”是一个非常糟糕的搜索关键字,我无法找到任何相关内容。

4

1 回答 1

6

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

Try
     // Do something
Catch ex As SqlException When ex.Number = 547
     // Constraint Violation
End Try

这使您免于捕获所有 SqlExceptions,然后检查Number属性,然后如果不匹配则必须重新抛出异常。

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

例如,如果您有一个相当普遍的异常,如 COMException,您通常只想在它表示某个 HRESULT 时捕获它。例如,当它表示 E_FAIL 时,您想让它不处理,但当它表示 E_ACCESSDEINED 时,您想抓住它,因为您有针对这种情况的替代方案。在这里,这是一个完全合理的条件 catch 子句:

Catch ex As System.Runtime.InteropServices.COMException When ex.ErrorCode() = &H80070005 

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

Catch ex As System.Runtime.InteropServices.COMException 
    If (ex.ErrorCode != &H80070005) Then Throw 

从逻辑上讲,这种“catch/rethrow”模式与过滤器所做的事情相同,但有一个微妙而重要的区别。如果异常未处理,则两者之间的程序状态完全不同。在 catch/rethrow 情况下,未处理的异常似乎来自 catch 块中的 Throw 语句。除此之外不会有调用堆栈,并且任何直到 catch 子句的 finally 块都将被执行。两者都使调试更加困难。在过滤器情况下,异常从最初的抛出点开始未处理,并且 finally 子句没有改变程序状态。

于 2013-10-16T10:24:54.637 回答