关于c#:例外:何时使用,计时,整体使用

Exceptions: When to use, timing, overall use

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

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

1
2
3
4
5
6
7
8
9
// _sValue is a string
try
{
    return float.Parse(_sValue);
}
catch
{
    return 0;
}

我把它改成:

1
2
3
4
5
6
7
8
9
float l_fParsedValue = 0.0f;
if (float.TryParse(_sValue, out l_fParsedValue))
{
    return l_fParsedValue;
}
else
{
    return 0;
}

结果,我在Visual Studio中的输出不再充满类似

First chance System.FormatException blabla

当类似"-"的字符串到达代码段时。我认为使用第二个片段更干净。

更进一步,我经常看到异常被使用得太频繁了,比如:"我在这个try-catch中做任何我想做的事情,如果发生任何错误,catch。"

现在,为了不被错误的观念所困扰,我希望你们能帮助我清楚地定义如何/何时使用这些例外,以及何时坚持"如果……否则"。

提前感谢您的帮助!


您应该在异常情况下抛出异常。也就是说,当一些意想不到的事情发生时。如果您期望一个函数定期抛出一个异常,这很可能是糟糕的设计。

在您的示例中,很明显TryParse更好,因为异常似乎经常发生。

但例如,在分析文件时,我希望它几乎总是有效的。所以我通常使用Parse来捕获异常并生成一个InvalidDataException,其中捕获的异常作为内部异常。通常会大大简化解析代码,即使它的风格可能不好。

我推荐EricLippers的博客条目:烦人的例外


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

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


如果是Parse()TryParse(),最好不要等待异常,使用色氨酸并自行采取不正确的输入。


Programs that use exceptions as part
of their normal processing suffer from
all the readability and
maintainability problems of classic
spaghetti code.

— Andy Hunt and Dave Thomas

我认为对于如何/何时使用异常没有简单正确的答案。它取决于您正在使用的应用程序的体系结构和其他因素。

我建议你读一下第8.3章。错误处理技术和8.4.代码完整书的例外情况。


到目前为止还没有深入研究的另一个问题是,例外是有代价的。它们破坏了程序中的正常控制流,结果导致了一些资源的使用。

一个简单的测试方法是编写一个程序,在原来的float上循环。用一些无效的数据解析代码,并比较运行时间和台盼版本-会有一个很小但明显的区别。

在决定异常时,我脑海中的一个片段来自本文:

Almost Rule #1

When deciding if you should throw an
exception, pretend that the throw
statement makes the computer beep 3
times, and sleep for 2 seconds. If
you still want to throw under those
circumstances, go for it.


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

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

注意这里有一个滑点——验证(用户输入)错误是否也应该作为异常抛出?一些思想流派说不(包括微软),一些说是。你的电话。每种方法都有其优点和缺点,并且由您决定如何构造代码。

捕获异常的经验法则是——您应该只捕获可以处理的异常。现在,这也很滑。是否向用户显示错误消息并"处理"它?但如果是臭名昭著的StackOverflowExceptionOutOfMemoryException呢?那时你几乎什么都不能显示。这些可能不是唯一能使整个系统处于不可用状态的例外。再说一遍-你的电话。