在我的應用程序中,如果特定類的屬性爲null或空(如果是字符串),則需要拋出異常。我不確定在這種情況下使用什麼樣的最佳例外。我討厭創建一個新的異常,我不確定在這種情況下ArgumentNullException是否合適。屬性不能爲空時使用什麼異常類型?
我應該創建一個新的異常還是有我可以使用的異常?
我不介意拋出一個ApplicationException。
在我的應用程序中,如果特定類的屬性爲null或空(如果是字符串),則需要拋出異常。我不確定在這種情況下使用什麼樣的最佳例外。我討厭創建一個新的異常,我不確定在這種情況下ArgumentNullException是否合適。屬性不能爲空時使用什麼異常類型?
我應該創建一個新的異常還是有我可以使用的異常?
我不介意拋出一個ApplicationException。
的MSDN guidelines for standard exceptions狀態:
做使用價值財產 制定者的隱含值參數的名稱。
以下代碼示例顯示一個 屬性,如果調用者傳遞一個空參數 ,該屬性將拋出異常。
public IPAddress Address { get { return address; } set { if(value == null) { throw new ArgumentNullException("value"); } address = value; } }
此外,MSDN guidelines for property design說:
避免拋出從 屬性獲取例外。
屬性獲取者應該是簡單的 操作沒有任何先決條件。 如果一個吸氣劑可能會拋出異常, 考慮重新設計屬性爲 是一種方法。此建議 不適用於索引器。索引器 由於無效的 參數而引發異常。
它是有效的,可接受的從屬性的setter拋出 例外。
在二傳手所以扔ArgumentNullException
上null
,並ArgumentException
對空字符串,什麼事都不做的吸氣劑。由於setter拋出並且只有你有權訪問後臺字段,所以很容易確保它不包含無效值。吸取投擲是毫無意義的。這可能是使用Debug.Assert
的好地方。
如果你真的不能提供適當的默認的話,我想你有三種選擇:
只返回無論是在性能和文檔這種行爲作爲使用合同的一部分。讓調用者處理它。您可能還需要構造函數中的有效值。儘管這可能完全不適合你的應用程序。
通過方法替換屬性:傳遞無效值時引發的setter方法,以及在屬性從未分配有效值時拋出InvalidOperationException
的getter方法。
從吸氣劑中拋出InvalidOperationException
,因爲您可以認爲「屬性從未分配過」是無效狀態。雖然你通常不應該從getter中拋出,但我想這可能是一個例外的好理由。
如果您選擇選項2或3,您還應該包括一個TryGet-方法返回一個bool
這表明如果屬性已被設置爲一個有效的值,如果是返回一個out
參數值。否則,你強制呼叫者準備好處理InvalidOperationException
,除非他們先前已經設置了屬性並因此知道它不會拋出。比較int.Parse
與int.TryParse
。
我建議使用選項2與TryGet方法。它不違反任何指導原則,並對調用代碼施加最低要求。
關於其他建議
ApplicationException
是太一般。 ArgumentException
對於null
有點過於籠統,否則就很好。MSDN docs again:
不要拋出最具體的(最派生)的例外是 合適。例如,如果一個方法 收到一個空值(基於Visual的 中的Nothing),它應該拋出 System.ArgumentNullException,而不是基類型的 System.ArgumentException。
其實你不應該使用ApplicationException
在所有(docs):
不要從T派生自定義異常:System.Exception類,而不是T:System.ApplicationException類。
它最初認爲自定義異常應該派生自ApplicationException類;然而,這並沒有被發現增加重要價值。有關更多信息,請參閱處理異常的最佳實踐。
InvalidOperationException
不旨在用於當所述參數的方法或屬性是無效的,但是,用於當操作作爲一個整體是無效的(docs)。它不應該從setter丟棄:
如果處於不適當的狀態,請拋出System.InvalidOperationException異常。給定對象的當前狀態,如果屬性集或方法調用不適合,則應引發System.InvalidOperationException。例如,寫入已打開讀取的System.IO.FileStream應該會引發System.InvalidOperationException異常。
順便提及,InvalidOperationException
是用於當操作是用於對象的當前狀態無效。如果整個課程的操作始終無效,則應使用NotSupportedException
。
構造函數是否將它設置爲非空值?如果是這樣,我只會從引用者那裏拋出ArgumentNullException
。
我會拋出一個InvalidOperationException
。 MSDN說它「在方法調用對於對象的當前狀態無效時引發」。
我不認爲這適用於這種情況。 InvalidOperationException只應在被調用的對象無效時使用。在這種情況下,被調用的對象是100%有效的,它是該方法的參數是無效的。 – JaredPar 2009-09-28 17:52:37
如果對象處於無法使用屬性設置器的狀態,則會拋出'InvalidOperationException'。也就是說,*操作*本身是無效的。 MSDN文檔給出了「寫入已打開閱讀的System.IO.FileStream」的示例。 – Joren 2009-09-28 17:54:28
我想我們並不知道所謂的確切場景。我正在假設我們正在調用一個類的方法,並試圖在該方法內使用該類的屬性。在這種情況下,該對象對於被調用的方法無效(因爲在調用方法之前需要設置該屬性)。 看起來@JaredPar正在考慮參數未初始化的場景。在那種情況下,他提出的「ArgumentException」是最有意義的。 – bdukes 2009-09-28 18:15:17
嗯,這不是一個參數,如果你引用一個類的屬性。所以,你不應該使用ArgumentException或ArgumentNullException。
NullReferenceException會發生,如果你只是讓事情孤單,所以我認爲這不是你想要的。
因此,使用ApplicationExeption或InvalidOperationException可能是您最好的選擇,確保給出一個有意義的字符串來描述錯誤。
我很確定在.NET Framework中有一些類從屬性的setter中拋出ArgumentException。我不記得確切的地方,但我記得遇到它。你可能會認爲它可能不是「正確的」,但是不管框架是否已經開創了先例。 – Tinister 2009-09-28 17:40:00
如果有人試圖指定爲空,那麼拋出ArgumentNullException是相當合適的。
屬性不應該拋出讀取操作。
你從哪裏獲得一個屬性永遠不會拋出讀操作的想法?它肯定可以輕鬆發生。 – 2009-09-28 17:37:52
@John我不認爲他的觀點是它不能但不能。 – 2009-09-28 17:41:56
@John Fisher:Cwalina,Krzystof和Brad Abrams:「Framework Design Guidelines,Conventions,Idioms,and Patterns for Reusable .Net Libraries」,Addison-Wesley,2006年。 121 - 其他來源。 – 2009-09-28 17:48:12
如果問題是一個參數的成員,而不是參數本身,那麼我認爲最好的選擇是更通用的ArgumentException
。 ArgumentNullException
在這裏不起作用,因爲參數實際上不是null。相反,您需要更通用的「您的參數有問題」異常類型。
的構造函數的詳細信息將是非常合適的位置
有一個將ArgumentNullException的解釋擴展爲意義「字符串參數爲null或空」的先例:在這種情況下,System.Windows.Clipboard.SetText將引發ArgumentNullException。
所以我不會在您的屬性設置器中使用此代碼而不是更常規的ArgumentException中發現任何錯誤,前提是您要記錄它。
只要錯誤信息對開發人員有幫助就拋出。無論如何,這類例外不應該發生在開發之外。
請記住太屬性是語法加糖的方法。 – Dykam 2009-09-28 19:00:49
一個相關的有趣的討論:http://stackoverflow.com/questions/1488472/best-practices-throwing-exceptions-from-properties – Joren 2009-09-28 19:08:52