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

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

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

还是我说错了?

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

清晰的 尊重你的方法

拍我。


当前回答

以下是我在博客中描述的最佳实践:

抛出异常以说明软件中的意外情况。 使用返回值进行输入验证。 如果您知道如何处理库抛出的异常,请在尽可能低的级别捕获它们。 如果出现意外异常,请完全放弃当前操作。不要假装你知道如何对付他们。

其他回答

让我们假设您有一个做一些计算的方法。它必须验证许多输入参数,然后返回一个大于0的数字。

使用返回值来表示验证错误,这很简单:如果方法返回的数字小于0,则发生错误。如何判断哪个参数无效?

我记得在我学习C语言的时候,很多函数返回的错误代码是这样的:

-1 - x lesser then MinX
-2 - x greater then MaxX
-3 - y lesser then MinY

etc.

它真的比抛出和捕获异常的可读性更差吗?

标准的回答是,异常是不正常的,应该在特殊情况下使用。

其中一个对我来说很重要的原因是,当我在维护或调试的软件中读取try-catch控制结构时,我试图找出为什么最初的编码器使用异常处理而不是if-else结构。我希望能找到一个好的答案。

请记住,您不仅为计算机编写代码,还为其他编码员编写代码。有一个与异常处理程序相关联的语义,您不能仅仅因为机器不介意就将其丢弃。

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

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

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

一般来说,在低级别处理异常本身并没有什么问题。异常是一个有效的消息,它提供了一个操作为什么不能执行的很多细节。如果你能接受,你就应该接受。

一般来说,如果你知道有很高的失败概率,你可以检查…你应该去检查一下…即if(obj != null) obj.method()

在你的情况下,我对c#库不够熟悉,不知道date time是否有一种简单的方法来检查时间戳是否越界。如果是,只需调用If (.isvalid(ts)) 否则,您的代码基本上没问题。

所以,归根结底,这取决于哪种方式可以创建更干净的代码……如果防止预期异常的操作比处理异常更复杂;那么你就有我的权限来处理异常,而不是到处创建复杂的守卫。