我在一个新的地方工作,在代码中看到很多东西我并不舒服。
我已经看到了很多这样的代码:
try
{
dAmount = double.Parse(((TextBox)control.Items[someRow].FindControl("txtControl")).Text);
}
catch
{
dAmount = 0;
}
我经常阅读stackoverflow等,我知道这是不对的,但我在辩论自己处理这个问题的最佳方法。
开发人员显然认为设置dAmount=0;
是处理异常的好方法,但是看看double.Parse
如何只能抛出3个异常(ArgumentNullException,FormatException,OverflowException),如果我们添加NullReferenceException以防万一FindControl
或其他对象返回null,然后在我看来,我可以覆盖所有的裂缝,但是代码看起来有点难看,而且我正在寻找建议,可能是更好的方法吗? / p>
这是我出来的
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
来电?欢迎任何建议。
答案 0 :(得分:3)
你对所有的异常做了完全相同的事情,这相当违背了将它们全部分开的目的。如果您打算对每种类型实际执行不同的操作,则应该捕获不同的异常。
即使没有例外情况,您的finally
区块也会运行并将您的值清零。
您不应该首先使用控制流的例外;您应该编写代码,以便在用户输入无效数据时不会抛出任何异常,而不是为非特殊用例抛出和捕获异常。在这种情况下,就像使用double.TryParse
一样简单。
例如空引用/空参数异常,溢出异常等异常应该永远不会被捕获到顶级方法之外,该方法在优雅失败之前记录任何致命异常。这些是愚蠢的例外;如果您收到它们,则表明您的代码中存在需要修复的错误,而不是您应该尝试扫描并继续执行程序的问题。
答案 1 :(得分: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
}
答案 2 :(得分:1)
您应该使用Double.TryParse
代替。
double number;
if (Double.TryParse(value, out number))
dAmount = number;
else
dAmount=0;
这更清洁,完全避免例外。
答案 3 :(得分: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在out param中为0。
这里真正的问题是......实际上是零吗?即是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"魔术值"并根据它做一些不同的事情?那就是你应该捕获的地方(或者,捕获并记录然后重新抛出)。
答案 4 :(得分:0)
尝试/捕获并不是为了控制方法的流程。如果你不能重新设计整件事,那我就做这样的事情。
public double Parse(...)
{
double value = 0;
string text = ((TextBox)control.Items[someRow].FindControl("txtControl")).Text;
double.TryParse(text, out value);
return value;
}