例外:何时使用、时机、总体使用
我会尝试提出我的问题,这样它就不会以简单的争论线索结束。
我最近开始研究用 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
当像“-”这样的字符串到达代码片段时, 。我认为使用第二个片段更干净。
更进一步,我经常看到异常被频繁使用,例如:“我在这个 try-catch 中做任何我想做的事,如果出现任何问题,就捕获。”。
现在,为了不陷入糟糕的误解,我希望你们帮助我清楚地定义如何/何时使用这些例外,以及何时坚持老派的“if...else”。
预先感谢您的帮助!
I'll try and ask my question so it doesn't end as a simple argumentative thread.
I've jumped into an application coded in C# recently and I'm discovering the exception mechanism. And I've had a few bad experiences with them such as the following
// _sValue is a string
try
{
return float.Parse(_sValue);
}
catch
{
return 0;
}
I changed it into :
float l_fParsedValue = 0.0f;
if (float.TryParse(_sValue, out l_fParsedValue))
{
return l_fParsedValue;
}
else
{
return 0;
}
Result, my Output in Visual Studio is not anymore flooded with message like
First chance System.FormatException blabla
when string like '-' arrive in the snippet. I think it's cleaner to use the second snippet.
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
在特殊情况下你应该抛出异常。即当意外发生时。如果您期望函数定期抛出异常,那么很可能是糟糕的设计。
在您的示例中,很明显
TryParse
更好,因为异常似乎经常发生。但例如在解析文件时,我希望它几乎总是有效的。所以我通常使用
Parse
并捕获异常并生成InvalidDataException
,并将捕获的异常作为内部异常。通常会大大简化解析代码,即使它可能是不好的风格。我推荐 Eric Lippers 的博客文章:令人烦恼的异常
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 aInvalidDataException
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
如果是
Parse()
/TryParse()
,最好不要等待异常,使用 TryParse 并自行处理不正确的输入。In case of
Parse()
/TryParse()
it's better don't wait for exception, use TryParse and act on incorrect input by yourself.异常应该用于异常行为,而不是用于流量控制。一个基本准则是,如果正常的程序流程经常遇到异常,那么您就做错了。
然而,值得注意的是,仅存在
try { } catch { }
本身不会对性能产生负面影响。仅当实际抛出异常并且需要计算堆栈跟踪时,您才会看到性能下降(在某些情况下相当严重)。Exceptions should be used for exceptional behavior, not for flow-control. A basic guideline would be that if normal program flow regularly runs into exceptions you're doing something wrong.
However, it is important to notice that just having a
try { } catch { }
present will itself not affect performance negatively. Only when an exception is actually thrown and the stack trace needs to be computed you will see (in some cases quite severe) performance degradation.我认为关于如何/何时使用异常没有简单的正确答案。这取决于您正在处理的应用程序的体系结构和其他因素。
我建议您阅读 8.3 章。错误处理技术和8.4。 《代码完整》一书的例外情况。
I think there is no simple right answer about how/when to use exceptions. It depends on an architecture of the application you're working on and other factors.
I can suggest you to read the chapters 8.3. Error-Handling Techniques and 8.4. Exceptions of the Code Complete book.
到目前为止尚未深入研究的另一点是异常是有成本的。它们破坏了程序中的正常控制流程,从而导致了一些资源的使用。
一个简单的测试是编写一个程序,循环使用一些无效数据的原始 float.Parse 代码,并比较运行时间与 TryParse 版本 - 会有一个微小但明显的差异。
在做出有关异常的决定时,我脑海中浮现的一个片段来自 这篇文章:
Another point that hasn't been examined in depth so far is that Exceptions have a cost. They subvert the normal flow of control in the program and there is some resource use as a result.
A simple test would be to write a program that loops over your original float.Parse code with some invalid data, and compare how long it takes to run versus the TryParse version - there will be a small but noticeable difference.
A snippet that sticks in my mind when making decisions about exceptions is from this article:
啊,要是这么简单就好了!但是,唉——何时使用异常的决定往往是主观的。不过,您仍然可以使用一些指南。例如,Microsoft 有一些。
总而言之,抛出异常的经验法则是 - 只有当函数无法执行其应做的事情时才抛出异常。基本上每个函数都有一个契约 - 它具有合法的输入值范围和合法的输出值范围。当输入值无效,或者无法提供预期的输出值时,您应该抛出异常。
请注意,这里有一个棘手的问题 - 验证(用户输入)错误是否也应该作为异常抛出?有些思想流派说不(包括微软),有些则说可以。你的电话。每种方法都有其优点和缺点,由您决定如何构建代码。
捕获异常的经验法则是 - 您应该只捕获您可以处理的异常。现在,这也很滑。向用户显示错误消息是否也在“处理”它?但如果是臭名昭著的
StackOverflowException
或OutOfMemoryException
该怎么办?那时你几乎无法显示任何东西。这些可能不是唯一可能导致整个系统处于不可用状态的例外情况。再说一遍——你的决定。Ahh, if only it was that simple! But, alas - the decision when to use exceptions is more often subjective than not. Still, there are guidelines you can use. For example, Microsoft has some.
All in all, the rule of thumb for throwing exceptions is - you only throw an exception when a function cannot do what it was supposed to do. Basically each function has a contract - it has a legal range of input values and a legal range of output values. When the input values are invalid, or it cannot provide the expected output values, you should throw an exception.
Note that there is a slippery point here - should validation (of user input) errors also be thrown as exceptions? Some schools of thought say no (Microsoft included), some say yes. Your call. Each approach has its benefits and drawbacks, and it's up to you to decide how you will structure your code.
A rule of thumb for catching exceptions is - you should only catch exceptions that you can handle. Now, this is also slippery. Is displaying the error message to the user also "handling" it? But what if it's the infamous
StackOverflowException
orOutOfMemoryException
? You can hardly display anything then. And those might not be the only exceptions that can leave the whole system in an unusable state. So again - your call.