为了避免所有我可以在谷歌上搜索到的标准答案,我将提供一个你们都可以随意攻击的例子。

c#和Java(以及其他很多语言)有很多类型,有些“溢出”行为我一点也不喜欢(例如type。MaxValue +类型。SmallestValue ==类型。MinValue,例如int。MaxValue + 1 = int.MinValue)。

但是,鉴于我的邪恶本性,我将通过将此行为扩展为重写DateTime类型来对这种伤害进行侮辱。(我知道DateTime在. net中是密封的,但为了这个例子,我使用了一种与c#完全相似的伪语言,除了DateTime没有密封之外)。

被覆盖的Add方法:

/// <summary>
/// Increments this date with a timespan, but loops when
/// the maximum value for datetime is exceeded.
/// </summary>
/// <param name="ts">The timespan to (try to) add</param>
/// <returns>The Date, incremented with the given timespan. 
/// If DateTime.MaxValue is exceeded, the sum wil 'overflow' and 
/// continue from DateTime.MinValue. 
/// </returns>
public DateTime override Add(TimeSpan ts) 
{
    try
    {                
        return base.Add(ts);
    }
    catch (ArgumentOutOfRangeException nb)
    {
        // calculate how much the MaxValue is exceeded
        // regular program flow
        TimeSpan saldo = ts - (base.MaxValue - this);
        return DateTime.MinValue.Add(saldo)                         
    }
    catch(Exception anyOther) 
    {
        // 'real' exception handling.
    }
}

当然,如果可以很容易地解决这个问题,但事实仍然是,我不明白为什么不能使用异常(从逻辑上讲,我可以看到,当性能是一个问题时,在某些情况下应该避免异常)。

我认为在许多情况下,它们比if结构更清晰,并且不会破坏方法所做的任何契约。

恕我直言,“永远不要在常规程序流程中使用它们”的反应似乎并不是每个人都有,因为这种反应的力量可以证明。

还是我说错了?

我读过其他的帖子,处理各种特殊情况,但我的观点是,如果你们都是:

清晰的 尊重你的方法

拍我。


当前回答

性能如何?在负载测试一个。net web应用程序时,我们在每个web服务器上模拟了100个用户,直到我们修复了一个常见的异常,这个数字增加到500个用户。

其他回答

除了上述原因之外,不使用异常进行流控制的另一个原因是它会使调试过程变得非常复杂。

例如,当我试图在VS中追踪一个错误时,我通常会打开“中断所有异常”。如果您正在使用异常进行流控制,那么我将定期在调试器中中断,并将不得不继续忽略这些非异常异常,直到我得到真正的问题。这很可能会让人发疯!!

我不认为使用异常来进行流控制有什么错。异常有点类似于延续,在静态类型语言中,异常比延续更强大,所以,如果你需要延续,但你的语言没有它们,你可以使用异常来实现它们。

好吧,实际上,如果你需要延续,而你的语言没有,你选择了错误的语言,你应该使用另一种语言。但有时你别无选择:客户端web编程就是最好的例子——没有办法绕过JavaScript。

An example: Microsoft Volta is a project to allow writing web applications in straight-forward .NET, and let the framework take care of figuring out which bits need to run where. One consequence of this is that Volta needs to be able to compile CIL to JavaScript, so that you can run code on the client. However, there is a problem: .NET has multithreading, JavaScript doesn't. So, Volta implements continuations in JavaScript using JavaScript Exceptions, then implements .NET Threads using those continuations. That way, Volta applications that use threads can be compiled to run in an unmodified browser – no Silverlight needed.

但是你并不总是知道在你调用的方法中发生了什么。您将无法确切地知道异常抛出的位置。不需要更详细地检查异常对象....

如果您对控制流使用异常处理程序,那么您就太笼统和懒惰了。正如其他人提到的,如果在处理程序中处理处理,就会发生一些事情,但究竟发生了什么?本质上,如果您将异常用于控制流,则您是在为else语句使用异常。

如果您不知道可能会发生什么状态,那么您可以使用异常处理程序处理意外状态,例如当您必须使用第三方库时,或者当您必须捕获UI中的所有内容以显示良好的错误消息并记录异常时。

但是,如果您知道哪里可能出错,而不使用if语句或其他检查方法,那么您就是懒惰。允许异常处理程序成为您知道可能发生的事情的所有人是懒惰的,它稍后会回来困扰您,因为您将试图根据可能错误的假设来修复异常处理程序中的情况。

如果您在异常处理程序中放入逻辑以确定究竟发生了什么,那么如果您没有将该逻辑放入try块中,那么您将非常愚蠢。

异常处理程序是最后的手段,当您无法阻止某些事情出错时,或者事情超出了您的控制能力。比如,服务器宕机并超时,而您无法阻止抛出异常。

最后,提前完成所有检查,显示您知道或预期会发生什么,并使其显式化。代码的意图应该清楚。你更愿意读什么?

您可以使用锤子的爪来拧螺丝,就像您可以为控制流使用异常一样。这并不意味着这是该特性的预期用途。if语句表示条件,其预期用途是控制流。

如果您以一种意想不到的方式使用特性,同时又选择不使用为此目的而设计的特性,那么将会有相关的成本。在这种情况下,清晰度和性能没有真正的附加价值。与广泛接受的if语句相比,使用异常能给您带来什么?

换句话说:你能做并不意味着你应该做。