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

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结构更清晰,并且不会破坏方法所做的任何契约。

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

还是我说错了?

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

清晰的 尊重你的方法

拍我。


当前回答

您是否曾经尝试调试一个在正常操作过程中每秒引发5个异常的程序?

我有。

该程序相当复杂(它是一个分布式计算服务器),在程序的一侧稍作修改,就可能很容易破坏完全不同的地方的某些东西。

我希望我可以启动程序,然后等待异常发生,但是在正常的操作过程中,在启动过程中大约有200个异常

我的观点是:如果你在正常情况下使用异常,你如何定位异常情况?

当然,还有其他强有力的理由不要过多使用异常,特别是在性能方面

其他回答

因为代码很难阅读,你可能在调试它时遇到麻烦,在很长一段时间后修复错误时,你会引入新的错误,在资源和时间方面更昂贵,如果你正在调试代码,调试器在每次异常发生时停止,这让你很恼火;)

异常基本上是非本地的goto语句,具有后者的所有结果。在流控制中使用异常违反了最小惊奇原则,使程序难以阅读(请记住,程序首先是为程序员编写的)。

而且,这不是编译器供应商所期望的。他们希望很少抛出异常,并且他们通常让抛出代码非常低效。抛出异常是。net中最昂贵的操作之一。

然而,一些语言(尤其是Python)使用异常作为流控制结构。例如,如果没有其他项,迭代器将引发StopIteration异常。即使是标准的语言结构(比如for)也依赖于此。

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

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

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

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

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

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

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

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

我真的不明白你是如何在你引用的代码中控制程序流的。除了ArgumentOutOfRange异常,您将永远不会看到其他异常。(所以你的第二个catch条款永远不会被击中)。您所做的只是使用代价极高的抛出来模拟if语句。

此外,您也没有执行更危险的操作,即仅仅抛出一个异常,以便在其他地方捕获它以执行流控制。你实际上是在处理一个特例。