區分 .NET 異常類型
出於對所有事物的熱愛,您如何區分預定義的 .NET 異常類中的不同“異常風格”?
例如,一段程式碼可能會
XmlException在以下情況下拋出一個:
- 文件的根元素為 NULL
- 文件中有無效字元
- 文件太長
所有這些都作為
XmlException對象拋出,所有內部的“告訴我更多關於這個異常的資訊”欄位(例如Exception.HResult、Exception.Data等)通常為空或 null。剩下
Exception.Message的就是唯一能讓你區分這些異常類型的東西,而且你不能真正依賴它,因為你猜到了,Exception.Message字元串是全球通用的,並且可以隨著文化的變化而改變。至少這是我對文件的閱讀。
Exception.HResult並且Exception.Data在 .NET 庫中被廣泛忽略。它們是世界上 .NET 錯誤處理程式碼的紅發繼子。即使假設它們不是,該HRESULT類型仍然是錯誤程式碼歷史上最糟糕、最糟糕的錯誤程式碼。為什麼我們仍然在 2010 年關注 HRESULT,這超出了我的理解。我的意思是,如果您正在執行 Interop 或 P/Invoke,那是一回事,但是…… HRESULT 在 System.Exception 中沒有位置。HRESULT 是 System.Exception 的長鼻上的一個疣。但說真的,這意味著我必須設置許多詳細的特定錯誤處理程式碼,以便找出應該作為異常數據的一部分傳遞的相同資訊。如果他們強迫你像這樣工作,例外是沒有用的。我究竟做錯了什麼?
編輯。一天后。
感謝所有的評論和回复。即使我還沒有完全解決具體問題,我也正在這裡學習一般課程(“錯誤消息很糟糕”)。這是我正在處理的特定場景。
我們的應用程序使用第三方生成的 XML 文件。這些 XML 文件有時包含在 XML 文件中真正無關的非法字元。這些非法字元會導致(驗證)XmlReader 因“X 行上的非法字元”異常而崩潰。但是,我們必須處理這些文件;我們不能簡單地告訴使用者,“抱歉,該文件沒有符合官方 XML 規範。”我們的使用者甚至不知道 XML 是什麼。
微軟在這種情況下(XML 文件包含非法字元的情況)有一個官方(對我來說很奇怪)建議:將文件載入到流中,迭代到包含錯誤的特定行(具有諷刺意味的是,在XmlException 對象),並將有問題的字元自定義替換為合法字元。然後嘗試再次將文件載入到驗證 XmlReader 中,並查看它是否崩潰。這是描述該技術的知識庫文章。
很好,我們正在這樣做,而且效果很好。問題是有時我們得到的這些 XML 文件在其他方面格式不正確:它們可能是空的,它們可能缺少結束標記等。因此,如果您遵循 MS 的建議,您實際上是在掛鉤您的“替換非法字元”邏輯到 catch 塊中,您可以在其中擷取驗證讀取器拋出的原始異常。
如果異常實際上是“非法字元”異常,那很好。但是,如果它是“缺少根元素”或“缺少結束標籤”異常,您會發現 MS 技術進入並替換有問題的字元本身就會爆炸,因為不僅沒有有問題的字元,而且在全部,或者有,但它們是無效格式的 XML,或其他。在這一點上,你處於一個雙重嵌套的漁獲之中,你的頭髮變灰並脫落,你的眼睛因咖啡因疲勞而呈深紅色,你正在質疑理智,更不用說效用了針對真實世界的 XML 使用驗證閱讀器。
所以我需要的是一種方法,在最初的 catch(XmlException) 塊中,這是“缺少根元素”還是“無效字元”異常,以便我可以採取適當的措施。我們不能做的一件事是阻止我們的使用者打開包含一些無效字元的文件。無論如何,我們都必須處理這些文件,我想唯一的解決方案是提前遍歷文件中的每個字元,將其視為文本流而不是 XML,找到非法字元,替換它們,然後用驗證 XmlReader 載入東西,如果它爆炸了,我們知道這不是非法字元異常,因為我們事先剝離了非法字元。
在這樣做之前,我想我至少會問 1)我們能否從 XmlException 對像中獲得更好的資訊,我希望有人能告訴我 2)“可以關閉 XmlException.Message 字元串。他們說它是本地化的,但是不是真的。這個字元串在 Windows 的所有版本和文化中都是相同的。
但沒有人告訴我。
原則上我完全同意你的看法,但是我真正關心引發異常的確切原因(在我的程式碼中)的實例數量非常少。
以 XmlException 為例,如果文件太長而不是包含無效字元,您的程式碼中是否真的會有一些不同的行為?
我能想到的唯一一個我真正關心的例子是 SQL 類型異常,可以從中恢復一些錯誤(例如失去的數據庫連接)。
和:
如果您在關閉錯誤消息時擔心文化,您可以在處理文件時將目前執行緒文化設置為不變文化,然後在完成後將其設置回原始文化。這應該確保消息始終相同。