2008-10-13 129 views
15

何時創建新的異常類型而不是使用.Net中的某個內置異常的指導原則是什麼?何時使用新的異常類型

讓我思考的問題是這樣的。我有一個WCF服務,這是一個基本的輸入輸出服務。如果服務無法創建輸出,因爲輸入無效,我想拋出一個異常,但是哪一個?

現在我只是拋出System.Exception的,但這並不覺得我的權利,我不知道爲什麼,就覺得這是不對的。 有一件事情讓我感到困惑,如果我用單元測試來測試它,並且期望system.Exception被拋出。這個異常也可以由框架或其他代碼拋出,而不是由我拋出的代碼拋出。然後測試會通過,因爲我得到預期的異常,但它應該失敗。

你有什麼建議?

+0

我認爲這適用於所有使用例外的語言。 – 2008-10-13 12:54:09

回答

15

避免引發System.ExceptionSystem.ApplicationException自己,因爲他們過於籠統。

對於WCF服務有故障合同 - 一般異常,你可以告訴subscibers處理。

標誌與接口:

[FaultContract(typeof(LogInFault))] 
void LogIn(string userName, string password, bool auditLogin); 

這時如果有一個例外,你可以拋出這個特定的故障:

throw new FaultException<LogInFault>(new LogInFault(), "message"); 

使用[DataContract]系列化上你的錯 - 這可以節省您不必處理所有通常需要的序列化異常。

+1

@基思 - 這很好。爲了更好地提供一個LoginFault的例子。 – RichardOD 2009-09-18 10:47:15

7

絕對避免拋出System.Exception除了一次性代碼之外的任何東西。

如果一個參數的方法是無效的,則拋出ArgumentException(或一些派生,更具體的例外)。在創建自己的例外之前,請參閱文檔瞭解現有例外情況 - 但這樣做通常很有用。 (當然,您可以從ArgumentException中派生出自己的異常類型 - 如果您想要從多個位置指示某種特定類型的條件,則創建新類型將提供更多信息,而不僅僅是將其放入錯誤消息中。 )

在WCF現在的錯誤處理可能是不同的錯誤「正常」的框架內處理 - 我建議你爲特定WCF的文檔/書籍。

+0

使用WCF時,通常需要區分由於服務器問題/錯誤導致的由客戶端(發送方)輸入引起的異常。 ArgumentException太普通 - 最好使用FaultContract。 – Joe 2008-10-13 13:47:54

0

總是創建一個新的異常類型(或使用標準類型,如果它適合你)。

在這種情況下,您可以將異常作爲一個組處理。

2

拋出System.Exception不是一個好主意。最大的原因是它對調用代碼的影響。他們應該如何處理異常?如果調用代碼要處理異常,那麼他們必須捕獲每個異常,這可能不是他們所做的最好的事情。

如果情況沒有覆蓋標準的例外之一,那麼你應該創建一個新的異常對象,如果該異常是,調用代碼將有望處理作爲一種特殊情況。

2

System.Exception只能用作Exceptions的基類,永遠不會被直接拋出。

框架已經提供了很多有效的異常類象的ArgumentException,ArgumentNullException,InvalidOperationException異常,出現FormatException,OverflowException異常,等...

你說你正在做的I/O的東西,所以一個好主意是看在框架中的類似操作(如int.Parse)併爲相似的錯誤拋出相同的異常。

或者從現有的異常類派生自己的異常類,如果它們都不符合您的需求。

1

什麼是何時 創建一個新的異常類型,而不是使用 在.NET中的內置異常 的一個準則?

當沒有合適的預定義的異常類時。
.NET FW非常豐富,通常可以找到預定義的異常。

如果該服務無法創建 輸出,因爲輸入是無效

ArgumentException Class (System)

當提供給的方法的其中一個參數 時引發的異常 無效。

0

如前面的海報所述,您不應該拋出System.Exception。事實上,如果您在代碼上運行FxCop,它會將其標記爲違反規則。

我建議查看Applied .NET Framework編程的第18章或通過C#(第2版)的更新CLR的第19章以獲取詳細指導。 Richter在糾正許多開發人員對例外的錯誤觀念方面做得非常出色。

這兩本書都包含由Framework Class Library定義的異常列表。查看列表並找出代碼可能拋出的最具體的例外情況。如果您可以從異常中恢復,請在該catch塊中執行此操作。如果您需要多個catch塊,請從最具體到最不具體的組織它們。如果在適合情況的現有列表中找不到一個,請創建自定義例外。

2

如果拋出System.Exception,那麼調用者必須捕獲System.Exception。這是一個禁忌,因爲它讓我們告訴用戶「那不起作用」,而不是更有用的東西。

如果調用方傳遞了無效參數,則ArgumentException非常有用。如果你的函數有一個int參數,你需要一個偶數,那麼你會拋出和ArgumentException告訴調用者什麼參數是無效的,爲什麼。但是,如果所有參數都有效但仍存在問題,則可能需要自定義異常。這樣呼叫者可以很快地告訴用戶出了什麼問題。

測試對我來說真的是在呼叫方。如果我有一打捕獲都做同樣的事情,那麼我真的只需要一個例外。然而,如果我有一個捕獲,並會有一個聲明告訴用戶三件事情出錯了,那麼我真的需要三個唯一的例外。