2010-11-04 34 views
1

說我有這樣的*的方法:當你知道你調用的方法會拋出同樣的東西時,你會拋出異常嗎?

public T GetItem(int index) 
{ 
    if (index < 0 || index >= _privateList.Count) 
    { 
     throw new ArgumentOutOfRangeException("index"); 
    } 

    return _privateList[index]; 
} 

你將包括throw或離開它?一方面,我覺得可以立即處理無效輸入,因爲這樣可以讓您在編寫實際的實現代碼時更加自信地處理您正在處理的內容。但在這種情況下,如果邊界檢查被省略,最終結果將大致相同(列表將拋出ArgumentOutOfRangeException而不是封閉類型)。

此外,由於上面的代碼檢查的東西,我,開發商,知道將反正檢查(在調用_privateList[index]),看來我正在做的代碼做更多的工作比它需要到上面,基本上執行兩次完全相同的一組比較。

任何有關這個問題的指導,將不勝感激。 *具體而言,我正在談論.NET(C#),但我會想象可能會問許多不同語言/框架的相同或相似問題 - 因此是「與語言無關」的標記。

回答

2

這是您在.NET框架中找到的那種代碼。它在那裏相當重要,源代碼是(不)可用。如果沒有包含參數檢查,您將得到一個很難診斷的異常。它轟炸隱形代碼,得出參數錯誤並不容易。

這與您編寫的代碼不太相關。但不是不存在,這取決於誰將成爲代碼的最終用戶。如果那是你,並且你維護代碼,那麼你在診斷原因時會遇到一些麻煩。如果是其他人,那麼重要的是他們可以隨時訪問源代碼的精確副本。如果那是混亂的,那麼不要猶豫,包括支票。

另一個考慮因素是當您部署代碼的發佈版本時發生的情況。沒有throw語句,這個特定的代碼很可能會被內聯。換句話說,你不會在棧頂看到GetItem()方法。這可以使查找異常的真正源更加困難,特別是因爲發佈堆棧跟蹤沒有行號。

然後成本是相關的。在這種情況下它非常低,如果Count屬性足夠便宜,則可能爲1納秒或2個。但該方法所做的實際工作也非常便宜。你的測試很容易使速度降低20%。這種方法可以非常好地深深嵌入到程序的關鍵路徑中。方法做得越多,額外測試的相關性就越小。

+0

完美的答案。感謝您從多個角度提供相關的想法。 – 2010-11-04 20:49:22

5

我儘量不要添加噪音(代碼沒有價值)。如果我的例外對我更有用,那麼我會拋出我的異常,但如果它們完全相同,那麼代碼的清晰性優先。

+0

如果你正在設計一個庫,正確地拋出ArgumentExceptions是一個非常好的主意。使您的課程與Microsoft設計.NET Framework的方式保持一致。開銷通常不是一個問題,因爲有太多的微軟方法會有這樣的檢查,以至於應用程序無論如何都會調用它。 – 2010-11-04 23:59:38

3

在.net 4中我將爲此條件定義代碼合同。在早期的.net版本中,我通常不會打擾手動拋出這樣的異常。

和IMO的庫代碼和應用程​​序代碼有很大的區別。在庫代碼中,我更關注定義良好的錯誤行爲,並且比我在應用程序代碼中完全拋出正確的異常。

1

我永遠不會拋出被調用方法拋出的異常。

但是我會(並且會!)拋出提供更多信息的異常 - 給出錯誤的上下文。

診斷隨機異常可能會非常困難,尤其是因爲通常缺少一些信息......就像堆棧跟蹤本身一樣。

要稍微修改您的例子:

public OrderLine GetOrderLineint index) 
{ 
    if (index < 0 || index >= _privateList.Count) 
    { 
     throw new ArgumentOutOfRangeException(
      "index", 
      "No OrderLine available at index " + index.ToString()); 
    } 

    return _privateList[index]; 
} 

這樣你仍然有剛夠調試信息結束。

相關問題