2013-10-16 28 views
6

與c#不同,VB.NET具有在Try/Catch/Finally塊中有條件地捕獲異常的功能。VB.NET Try/Catch/When - 離開還是有用?

我以爲我在某處讀到這通常是不好的做法,因爲它鼓勵人們把(商業)邏輯放在異常處理機制中,而且你基本上最終得到了榮耀的GoTo

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

那麼,有沒有合法的情況下才使用When功能還是應該遠離它?

這有可能已經被回答,但我無法找到任何有關由於「當」是一個搜索一個非常糟糕的關鍵字。

+0

可能是值得的編輯指出,異常過濾器是現在C#(違反第一句的問題)可用 –

回答

5

我能想到的通常情況是,當你只是想捕捉特定的異常,基於該異常的內容。例如: -

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

從捕獲所有SqlException S保存你,然後檢查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塊中的Throw語句。除此之外,將不會有任何調用堆棧,並且任何最終到達catch子句的塊都將被執行。兩者都使調試更加困難。在過濾器的情況下,異常從原始的拋出點處未處理,並且沒有程序狀態被final子句改變。

+0

FWIW ......我的理解是所有其他的事情(捕原來,審查數字,重擲)仍然發生。只是現在你所維護的代碼不需要直接處理它。 –

+0

@JoelCoehoorn - CLR異常處理機制中內置了異常過濾器。這不像是VB(和C#現在)編譯器實際上插入了這段代碼。事實上,異常過濾器比任何手動處理都要早(例如,他們實際上在*任何內部的'finally'子句之前觸發*) –