2013-01-19 172 views
33

我有以下代碼:如何在不丟失C#中的任何信息的情況下將消息添加到異常?

catch(Exception ex) 
{ 
    throw new FatalException("An error occurred while trying to load the XSLT file.", ex); 
} 

這只是不幸的是吞噬了異常。我可以通過以下操作解決此問題:

catch(Exception ex) 
{ 
    throw; 
} 

但我還是想包括與事件日誌幫助自定義消息。

如何將此消息添加到異常而不丟失任何信息? (堆棧跟蹤/調試符號等)

+0

在'FatalException'上添加原始異常作爲'InnerException'? –

+0

它在'throw new FatalException(「message」,ex)'末尾。 – krillgar

+0

爲什麼你想要做你的展示?只捕捉你可以做的事情。否則,讓他們冒泡。 – Mark

回答

13

原始異常仍然存在。

當您執行異常日誌記錄時,您收到的異常將是您對消息所做的FatalException。原來的例外是在ex.InnerException。您可以繼續循環通過InnerException,直到它爲空以獲取所有堆棧跟蹤信息等。

0

總之,不要。

我敢肯定,你可以通過一些反思找到解決這個問題的方法,但我會強烈推薦。它違背了.NET中的例外原始設計。例外情況不僅僅是爲了幫助記錄,它們提供了關於應用程序故障的原始原因的信息。

通常首選使用第一個選項,因爲它維護原始異常的堆棧跟蹤,但允許您通過將其包含在單獨的異常中來提供其他信息。在我自己的代碼中,無論何時我記錄異常,我的日誌記錄函數都會遞歸通過InnerException屬性來查找有關錯誤的所有有用信息。

+0

「記錄」可能不是用於此目的的最佳術語。如果您在遠程執行某些操作,那麼當您無法訪問任何日誌記錄時,只需發送特定類型的例外的電子郵件即可。 – krillgar

46

如果您只需要將信息添加到原始異常(例如用戶可讀的消息或特定的詳細信息,這些信息對於追蹤錯誤非常有用,但對最終用戶不會有用)可以使用異常的Data屬性,它是一個鍵/值對字典。

我們廣泛使用它來記錄信息,例如正在執行的報告或正在處理的文件,以便操作可以確定發生錯誤時發生了什麼。用戶不需要這些細節,因爲他們直接處理失敗的原因。

您也可以使用它傳遞一個純文本消息,對用戶有意義。唯一的問題是您將不得不在日誌框架或最終用戶界面中執行一些額外的工作,以便提取數據並使其對用戶有用。

例如,你可以這樣做:

catch (Exception ex) 
{ 
    ex.Data.Add("UserMessage", "An error occurred while trying to load the XSLT file."); 
    throw; 
} 

然後在客戶端代碼,你可以測試一下,看看是否UserMessage存在,如果是這樣,它呈現給用戶,而不是例外:

catch (Exception ex) 
{ 
    if (ex.Data.Contains("UserMessage")) 
    { 
     MessageBox.Show(ex.Data["UserMessage"].ToString()); 
    } 
    else 
    { 
     MessageBox.Show(ex.Message); 
    } 
} 
+2

更好的是'ex.Data [「UserMessage」] + =「發生錯誤...」;'這樣如果一些較低級別的代碼已經添加了一條消息,它會附加額外的文本而不是拋出一個['ArgumentException'](http://msdn.microsoft.com/en-us/library/system.collections.idictionary.add(v = vs.110).aspx#ddueExceptionsToggle) – KyleMit

+0

太棒了,謝謝!這些額外的數據也會自動添加到.NET跟蹤日誌中,並且如果您在try/catch鏈中一直使用唯一的密鑰和描述性消息,則無需花時間尋找錯誤的原因。 – Joel

+0

這樣做的好處是什麼,而不是拋出一個新的異常,並根據接受的答案將原始內容作爲innerException傳入? – ajbeaven

相關問題