2014-09-26 214 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“魔法值”,并根据它做出不同的事情?这就是你应该捕获的地方(或者捕获并记录然后重新抛出)。