【问题标题】:VB.NET Try/Catch/When - Stay away or does it have its use?VB.NET Try/Catch/When - 远离还是有它的用处?
【发布时间】:2013-10-24 09:36:01
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 可能值得编辑指出异常过滤器现在在 C# 中可用(与问题中的第一句话相反)

标签: vb.net exception-handling


【解决方案1】:

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

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

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

另见The good and bad of exception filters

例如,如果您有一个相当普遍的异常,例如 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 子句没有改变程序状态。

【讨论】:

  • fwiw... 我的理解是所有其他事情(抓住原件,检查数字,重新投掷)仍然会发生。只是现在你维护的代码不用直接处理了。
  • @JoelCoehoorn - 异常过滤器内置于 CLR 异常处理机制中。 VB(和现在的 C#)编译器实际上并没有插入此代码。并且异常过滤器实际上比任何手动处理都更早启动(例如,它们实际上在 任何内部 finally 子句行为之前触发)
猜你喜欢
  • 1970-01-01
  • 2017-06-29
  • 2011-01-29
  • 1970-01-01
  • 2011-07-02
  • 2010-09-15
  • 2020-07-11
  • 2011-02-04
  • 2011-04-13
相关资源
最近更新 更多