2014-09-26 93 views
0

我正在一個新的地方工作,在代碼中看到很多東西,我不太喜歡。正確捕捉異常.net

我已經看到了很多這樣的代碼:

try 
{ 
    dAmount = double.Parse(((TextBox)control.Items[someRow].FindControl("txtControl")).Text); 
} 
catch 
{ 
    dAmount = 0; 
} 

我讀計算器等的頻繁,我知道這是不對的,但我自己辯論有關的最佳方式來處理這個問題。

顯然認爲設置dAmount=0;是處理異常的好辦法,但看到如何double.Parse只能扔3個例外(ArgumentNullException,出現FormatException,發生OverflowException),如果我們的情況下,添加的NullReferenceException的FindControl或其他物體回來的開發null,那麼在我看來,我可以覆蓋所有的裂縫,但代碼看起來很醜,我正在尋找建議,也許有更好的方法?

這是我想出了

try 
{ 
    dAmount = double.Parse(((TextBox)control.Items[someRow].FindControl("txtControl")).Text); 
} 
catch (NullReferenceException nullRefEx) 
{ 
    dAmount = 0; 
    nwd.LogError("***Message: " + nullRefEx.Message + " ***Source: " + nullRefEx.Source + " ***StackTrace: " + nullRefEx.StackTrace); 
} 
catch (ArgumentNullException argNullEx) 
{ 
    dAmount = 0; 
    nwd.LogError("***Message: " + argNullEx.Message + " ***Source: " + argNullEx.Source + " ***StackTrace: " + argNullEx.StackTrace); 
} 
catch (FormatException frmEx) 
{ 
    dAmount = 0; 
    nwd.LogError("***Message: " + frmEx.Message + " ***Source: " + frmEx.Source + " ***StackTrace: " + frmEx.StackTrace); 
} 
catch (OverflowException ovrEx) 
{ 
    dAmount = 0; 
    nwd.LogError("***Message: " + ovrEx.Message + " ***Source: " + ovrEx.Source + " ***StackTrace: " + ovrEx.StackTrace); 
} 

BTW,我不控制日誌記錄功能是從另一支球隊在這裏,我知道是怎麼樣的醜陋。

如何在一般的Exception中保存例外情況,最後只有一個nwd.LogError調用?歡迎任何建議。

+1

你應該只是使用TryParse,如果它返回false do dAmount = 0 – 2014-09-26 17:45:02

+0

得說我不知道​​我怎麼沒有想到,你的評論應該是一個答案它的最佳答案:P – Termiux 2014-09-26 17:47:40

+0

我會添加一個答案。 – 2014-09-26 17:48:10

回答

1

您應該使用Double.TryParse代替。

double number; 
if (Double.TryParse(value, out number)) 
    dAmount = number; 
else 
    dAmount=0; 

這是更清潔,完全避免例外。

+0

這裏的if/else是多餘的,如果解析失敗,'number'已經是'0'。 – Servy 2014-09-26 17:52:40

+2

你說得對。儘管如此,我更喜歡它是明確的,但它使得閱讀更清晰一些。 – 2014-09-26 17:54:23

3
  1. 你對所有的例外都做了完全一樣的事情,而這些例外與它們分開抓住它們的目的相反。如果你打算實際做一些與每種類型不同的事情,你應該捕捉不同的例外。

  2. 您的finally塊將運行並將您的值清零,即使沒有例外。

  3. 您不應該首先使用控制流的異常;您應該編寫代碼,以便在用戶輸入無效數據時根本不會拋出任何異常,而不是拋出並捕獲非例外用例的異常。在這種情況下,就像使用double.TryParse一樣簡單。

  4. 例外情況如空引用/空參數異常,溢出異常等應該幾乎不會在頂級方法之外被捕獲,這些方法在優先失敗之前會記錄任何致命異常。這些是頭腦特例;如果你得到它們,這表明你的代碼中有一個需要修復的錯誤,而不是你應該試着在地毯下掃描並繼續執行程序的問題。

+0

好的一點,處理所有異常同樣會影響目的。 – Termiux 2014-09-26 17:51:29

1

不要使用finally,因爲這將始終設置dAmount = 0,即使沒有拋出異常。如果你想抓住一般的Exception,那麼一個catch (Exception ex)就足夠了。如果你想趕上那些具體的,我會做到以下幾點:

try 
{ 
    // code here 
    ... 
} 
catch (Exception ex) 
{ 
    if (ex is NullReferenceException || ex is ArgumentNullException 
      || ex is FormatException || ex is OverflowException) 
    { 
     // handle ex 
     ... 
     return; 
    } 
    throw; 
} 

在你的情況,你最好的選擇是可能使用Double.TryParse,就像這樣:

double amount; 
if(Double.TryParse(someValue, out amount) 
{ 
    // do something with amount... 
} 
else 
{ 
    // handle the error condition here 
} 
0

Try/Catch沒有控制你的方法的流程。如果你不能重新設計整個事情,那麼我會做這樣的事情。

public double Parse(...) 
{ 
    double value = 0; 
    string text = ((TextBox)control.Items[someRow].FindControl("txtControl")).Text; 
    double.TryParse(text, out value); 
    return value; 
} 
1

捕獲一個涵蓋所有這些實例的異常。日誌文件中的消息應該區分拋出哪種類型的異常。

string s = ....; 
double d = 0; 
try { 
    d = Double.Parse(s); 
} catch (Exception ex) { 
    //Set default value 
    nwd.LogError("***Message: " + ex.Message + " ***Source: " + ex.Source + "***StackTrace: " + ex.StackTrace); 
} 

其他答案缺少的關鍵在於他要記錄異常...的TryParse不會告訴你爲什麼沒有正確解析,它只是返回false和0的出PARAM。

這裏真正的問題是......其實是特別的零?即是0不是一個人輸入文本框的有效數字?程序的其餘部分如何判斷用戶是否輸入了零,或者零是由於解析錯誤返回的默認值?

更好的計劃,一個當我得到一個值對象,並可能失敗是使用可空我用...

string s = ....; 
double? d = null; 
try { 
    d = Double.Parse(s); 
} catch (Exception e) { 
    nwd.LogError("***Message: " + ex.Message + " ***Source: " + ex.Source + "***StackTrace: " + ex.StackTrace); 
} 
return d; 

現在調用者知道一個事實,即你的時候發生錯誤返回null(與一些「魔術值」相比)。使用「魔法值」不必要地使語義複雜化。

更好的辦法是簡單地讓錯誤傳播(或重新拋出)到實際可以合理處理的地方。你的代碼中的哪部分目前正在檢查0「魔法值」,並根據它做出不同的事情?這就是你應該捕獲的地方(或者捕獲並記錄然後重新拋出)。