2009-10-10 92 views
2

如果我有一個特定的異常,我期望它會發生; 並且爲了處理它,例如,我選擇在其發生時顯示錯誤消息,這會更好地執行,爲什麼?這是異常處理的更好的做法?

解釋性代碼:

try 
{ 
    string result = dictionary[key]; 
} 
catch (KeyNotFoundException e) 
{ 
    //display error 
} 

或:

if(!dictionary.ContainsKey(key)) 
{ 
    //display error 
} 
+4

你的例子讓我有點que,不安,因爲它似乎是自由混合「邏輯材料」和「顯示材料」。 EG,如果有人想在命令行應用程序中重用您的業務邏輯呢?通常,更好的方法是讓邏輯函數累積錯誤並將它們返回給調用者,調用者可以決定如何處理這些錯誤。 – RossFabricant

+1

rossfabricant,你應該看到我使用的代碼。業務邏輯和業務規則被認爲是相同的,所以所有業務邏輯都處於顯示級別或數據訪問級別。當我問及如何將業務邏輯提取到自己的邏輯層時,我被告知另一個層次的間接性是沒有必要的。我不同意,但也許穆斯塔法的情況也是如此。最佳做法+1。 –

回答

12

通常,異常用於指示異常情況 - 通常不會發生的情況,但您的程序仍然需要優雅地處理(例如文件不可訪問或只讀,網絡連接斷開)。正常控制流程,如檢查字典中的值,如果存在具有相同效果但不使用例外的等效函數,則不應使用例外。

在代碼中增加了try/catch語句還會使其不易讀,並且在代碼塊周圍出現異常處理程序會在CLR上施加一些限制,從而導致性能下降。

在你的榜樣,如果預計該詞典將有一定的鍵值,我會做類似

string result; 
if (!dictionary.TryGetValue(key, out result) 
{ 
    // display error 
    return; // or throw a specific exception if it really is a fatal error 
} 

// continue normal processing 

這比僅僅有一個異常處理程序輪的元素訪問

更清晰了很多
+1

您能否提供最後一條陳述的來源(或證明)?我沒有意識到這一點。我的理解是,只要你不拋出異常,try/catch塊就基本上不受性能方面的影響。 – Steve

+0

我記得一本書,我需要在星期一進行檢查。首先,CLR不會內聯具有異常處理程序的方法 - http://blogs.msdn.com/davidnotario/archive/2004/11/01/250398.aspx – thecoop

+1

@Steve:是的,如果你不喜歡拋出一個異常,進入/退出try塊的perf per hit只有微不足道的。問題是,如果它是一個可能不存在密鑰的預期條件,那麼應該使用更好/更簡單的機制(ContainsKey或TryGetValue)。 –

3

第二approuch更好。拋出異常可能非常昂貴。

2

第二種方法更好至少有3個原因:

1)它更清晰。作爲你的代碼的讀者,我希望有一個異常表明出現了問題,即使它被處理了。

2)使用Visual Studio進行調試時,通常會打破所有的異常,這使得處理總是拋出異常的代碼變得非常煩人。

3)第二個版本更快,但效果非常小,除非您在時間關鍵的代碼塊中每秒拋出許多例外。

1

第二種方法更好,因爲拋出和拋出異常的性能受到影響。大於100每秒的投射率可能會顯着影響大多數應用程序的性能。考慮Exceptions and Performance

1

當您需要提供一種簡單的方式擺脫困境時,異常處理最爲有用 - 它可以極大地簡化代碼並降低出現錯誤的可能性。

它在這樣的非常簡單的情況下幾乎沒有什麼優勢,並且由於它的性能,在這種情況下不應該使用罰分。

0

這一切都取決於你的應用程序在做什麼以及特定的代碼在做什麼。

由於thecoop說例外應該用於例外情況。作爲插圖寫入文件。如果檢查文件的存在會減慢應用程序的運行速度,並且/或者文件的缺失是一個嚴重的問題,則允許發生異常並將其捕獲。如果它不那麼重要或者重新創建文件不是問題,那麼首先進行文件存在檢查。

我已經看到了它認爲所有的錯誤處理應該通過例外(在Clean Code by Robert Martin最近)來完成,但我不同意。

7

都不是。

第二個選項是比第一更好。如你所期望的那樣正常發生,最好避免這種例外情況。例外情況最好只用於例外情況,即不能輕易預測和測試的情況。

最好的選擇但是就是TryGetValue方法,因爲它都檢查並獲取:

if (dictionary.TryGetValue(key, out result)) { 
    // use the result 
} else { 
    // display error 
} 
-2

只是一個提醒。這不是一個例外。 異常聽起來像「我的UNIX機器上沒有/ etc」。 如果你弄錯了,你會寫錯誤的代碼,如上所示。

+0

你能詳細說明你的意思嗎? – thecoop

+0

「我的UNIX計算機上沒有/ etc」 - 關於「is」或「is not」的着名示例在討論異常處理時是一個例外。滑稽... – Test

0

它很大程度上取決於字典的意義。如果由於程序設計而不能找到密鑰的可能性很高,那麼您應該嘗試使用trygetvalue。但是,如果程序的設計是這樣的,即找不到密鑰是例外事件,則應該使用異常處理程序方法。

2

第二種方法可能會更好。請記住,例外情況用於例外情況。使用此原則來指導您的決定:

  • 如果您要求密鑰作爲應用程序不變量存在於字典中,則假定它存在並處理異常(如果它不存在)。
  • 如果您的應用程序代碼不需要該條目在字典中,然後調用ContainsKey()第一。

我的猜測是,後者可能是正確的行動路線。

免責聲明:我一般避開了意見,性能應該是首要考慮的問題在這裏。一旦你證明你有瓶頸,只有讓性能影響你的決定!之前的任何事情都是premature optimization,並且會導致不必要的複雜應用程序代碼。