1

我会试着问我的问题,这样它就不会以一个简单的争论话题结束。

我最近跳进了一个用 C# 编码的应用程序,我发现了异常机制。我和他们有过一些不好的经历,比如以下

// _sValue is a string
try
{
    return float.Parse(_sValue);
}
catch
{
    return 0;
}

我把它改成:

float l_fParsedValue = 0.0f;
if (float.TryParse(_sValue, out l_fParsedValue))
{
    return l_fParsedValue;
}
else
{
    return 0;
}

结果,我在 Visual Studio 中的输出不再充斥着类似的消息

第一次机会 System.FormatException blabla

当像'-'这样的字符串到达​​片段时。我认为使用第二个片段更清洁。

Going a step further, I've often seen that exceptions are too often used ilke: "I do whatever I want in this try-catch, if anything goes wrong, catch.".

Now in order to not get stuck with bad misconceptions, I would like you guys to help me clearly define how/when to use those exceptions and when to stick with old school "if...else".

Thanks in advance for your help!

4

6 回答 6

5

You should throw exception in exceptional cases. i.e. when something unexpected happens. If you expect a function to regularly throw an exception that's most likely bad design.

In your examples it is very clear that TryParse is better since the exception seems to occor often.

But for example when parsing a file, I expect it to be almost always valid. So I usually use Parse and catch the exception and generate a InvalidDataException with the caught exception as inner exception. Usually simplifies the parsing code a lot, even if it may be bad style.

I recommend Eric Lippers's blog entry: Vexing exceptions

于 2011-05-31T08:11:00.410 回答
2

In case of Parse()/TryParse() it's better don't wait for exception, use TryParse and act on incorrect input by yourself.

于 2011-05-31T08:11:43.327 回答
2

异常应该用于异常行为,而不是流控制。一个基本的指导方针是,如果正常的程序流程经常遇到异常,那么你就做错了。

然而,重要的是要注意,仅仅拥有一份try { } catch { }礼物本身不会对绩效产生负面影响。只有当实际抛出异常并且需要计算堆栈跟踪时,您才会看到(在某些情况下非常严重)性能下降。

于 2011-05-31T08:12:51.760 回答
1

使用异常作为其正常处理一部分的程序会遇到经典意大利面条代码的所有可读性和可维护性问题。

——安迪·亨特和戴夫·托马斯

我认为关于如何/何时使用异常没有简单的正确答案。这取决于您正在处理的应用程序的架构和其他因素。

我可以建议你阅读第8.3 章。错误处理技术8.4。Code Complete书的例外情况

于 2011-05-31T09:00:44.313 回答
1

到目前为止尚未深入研究的另一点是异常是有代价的。它们破坏了程序中正常的控制流程,因此会占用一些资源。

一个简单的测试是编写一个程序,用一些无效数据循环你的原始 float.Parse 代码,并比较运行所需的时间与 TryParse 版本 - 会有一个小的但明显的差异。

在做出有关异常的决定时,我脑海中的一个片段来自这篇文章

几乎规则#1

在决定是否应该抛出异常时,假装 throw 语句使计算机发出 3 次哔哔声,然后休眠 2 秒。如果你仍然想在这种情况下投掷,那就去吧。

于 2011-05-31T08:39:40.293 回答
0

啊,要是就这么简单就好了!但是,唉 - 何时使用异常的决定往往是主观的。不过,您可以使用一些指导方针。例如,微软有一些.

总而言之,抛出异常的经验法则是——你只在函数不能做它应该做的事情时抛出异常。基本上每个函数都有一个契约——它有一个合法的输入值范围和一个合法的输出值范围。当输入值无效或无法提供预期的输出值时,您应该抛出异常。

请注意,这里有一个棘手的问题 - 验证(用户输入)错误是否也应该作为异常抛出?有些学派说不(包括微软),有些说是。你的来电。每种方法都有其优点和缺点,由您决定如何构建代码。

捕获异常的经验法则是 -您应该只捕获您可以处理的异常。现在,这也很滑。向用户显示错误消息是否也在“处理”它?但是,如果它是臭名昭著的StackOverflowExceptionorOutOfMemoryException呢?那时你几乎不能显示任何东西。这些可能不是唯一可能使整个系统处于不可用状态的例外情况。再说一次 - 你的电话。

于 2011-05-31T08:22:44.177 回答