2010-01-11 76 views
4

在.NET中捕捉異常時,可以根據需要使用特定類型的異常塊。但我通常會嘗試擁有至少一個「常規」異常catch塊。但有沒有辦法獲得被泛型異常處理程序捕獲的「真正」異常的類型,也許使用反射?捕捉一般異常時,如何確定原始異常類型?

舉例來說,如果我有

Catch ex As System.ServiceModel.FaultException(Of InvalidUser) 
    ProcessModuleLoadException(Me, ex) 
Catch ex As System.ServiceModel.FaultException(Of SQLExceptions) 
    ProcessModuleLoadException(Me, ex) 
Catch ex As System.ServiceModel.FaultException(Of DataNullReference) 
    ProcessModuleLoadException(Me, ex) 
Catch ex As System.ServiceModel.FaultException 
    ProcessModuleLoadException(Me, ex) 
Catch ex As Exception 
    ProcessModuleLoadException(Me, ex) 

(我讓他們爆發的調試,即使我做每個異常的同樣的事情)。我想檢查「ex」並獲得基本的「真實」類型的異常,或者作爲一種類型(主要是爲了調試,所以我可以添加另一種類型的異常catch塊)或者作爲一個字符串(用於日誌記錄)。

但是,在Catch塊內部,「ex」已經被轉換爲它的父類,因此任何有關原始異常的原始屬性和信息似乎都會丟失。

對此提出建議?

回答

13

即使Exception已經投給它的父類,你仍然可以調用GetType獲得其底層的具體類型(原諒我的C#):

try { 
    // Do stuff 
} 
catch(Exception ex) { 
    Type exceptionType = ex.GetType(); 
} 

如果這僅僅是用於診斷目的,你可以登錄ex.ToString(),其包括通過默認(除了堆棧跟蹤等)的基礎類型是這樣的:

System.ArgumentException: lastName 
    at Tests.Program.Main(String[] args) in ...\Program.cs:line 22 
+2

@downvoter:這個(和runrunraygun的)答案有什麼問題? – 2011-02-12 12:57:14

0

如何捕捉它作爲一個通用的系統異常,然後使用「is」術語來測試實際類型?

try 
{ 
    // Something 
} 
catch(Exception ex) 
{ 
    // Single catch block - catches as generic system exception 
    if(ex is FaultException) { 
     //Process as FaultEx 
    } 
    if(ex is ArithmeticException) { 
     //Process as ArithEx 
    } 
    if(ex is ArgumentException) { 
     //Process as ArgEx 
    } 
} 
finally 
{ 
    //Cleanup 
} 
+1

我從來沒有在生產代碼中看到過這樣的事情,對我而言,感覺就像是一種輕微的不自然的事情,讓你在大if語句中重現內置特性(多個catch塊)。這種方法有什麼優勢嗎? – gingerbreadboy 2010-01-11 21:09:36

+0

如果它仍然有效,我可以看到,如果您將「ex」傳遞給一個方法,然後迭代不同的異常類型以便將它們記錄在中心位置,那麼該方法將非常有用。 – 2010-01-12 15:16:57

+0

我總是捕獲特定的異常和相應的過程,但我已經構建了「錯誤記錄器」和「錯誤電子郵件程序」,它們使用此設置在方法簽名中採用通用前綴,並在某處反射記錄堆棧/電子郵件地址。 當我想記錄/發送除x,y和z以外的所有類型的電子郵件時,if語句開始起作用。 – 2010-01-12 16:03:02

2

這隻能從傑夫的答案稍作修改:

我一直在尋找的東西,像什麼克里斯描述,具體我想處理原始例外,它已被少數通用再次拋出後異常,並且只有一個處理程序可供我爲所有入口點調用。而且由於重新拋出一個異常會用它自己的異常類型來包裝它,我們需要添加循環來檢查內部異常,並檢查拋出的第一個異常。

因此,這裏是我結束了代碼:

Public Sub HandelException(myEx As Exception) 
    Try 
     Dim InnerEx As Exception = myEx 
     Do Until InnerEx.InnerException Is Nothing 
      InnerEx = InnerEx.InnerException 
     Loop 

     If InnerEx.GetType = GetType(Exception1) Then 
      'Handle exception type 1 
     ElseIf InnerEx.GetType = GetType(Exception2) Then 
      'Handle exception type 2 
     ElseIf InnerEx.GetType = GetType(Exception3) Then 
      'Handle exception type 3 
     ElseIf InnerEx.GetType = GetType(Exception4) Then 
      'Handle exception type 4 
     ElseIf InnerEx.GetType = GetType(Exception) Then 
      'Handle generic system exception 
     End If 
    Catch ex As Exception 
     'Handel unlikely exception in exception handler LOL. 
    End Try 
End Sub 

這樣做的好處是,你可以有你處理整個程序中,有很多的處理代碼異常類型的範圍廣泛,但你可以在一個地方處理它們。

我知道這個回覆對於這個問題有點遲,但是我想我會分享一下,或許是爲了幫助那些尋找我正在尋找的東西的人。