有没有理由抛出DivideByZeroException?

时间:2010-04-08 15:49:28

标签: c# exception-handling argumentnullexception dividebyzeroexception

有什么情况可以避免可以避免的throw错误吗?

我正在考虑DivideByZeroExceptionArgumentNullException

例如:

double numerator = 10;
double denominator = getDenominator();

if( denominator == 0 ){
   throw new DivideByZeroException("You can't divide by Zero!");
}

有没有理由抛出这样的错误?

注意:我不是在谈论捕捉这些错误,而是专门知道是否有充分理由抛弃这些错误。

只需重新评估

我知道在我给你的例子中你可能会更好地处理错误。也许这个问题应该改写一下。是否有任何理由throw其中一个错误,而不是在位置处理错误。

16 个答案:

答案 0 :(得分:20)

假设您编写了一个库来处理不适合Int64的大整数,那么您可能希望为您编写的除法算法抛出DivideByZeroException。

答案 1 :(得分:12)

.NET运行时已经非常善于抛出这些异常。它们也高度描述了什么是错误的,你不能在异常消息中添加任何好的评论。 “你不能除以零”没有增加价值。

但是,您可以通过筛选客户端代码传递的值来避免许多这些异常。如果客户端代码传递了null,那么你会希望ArgumentNullException具有参数名称,当它传递一些可能导致DivideByZero错误的东西时,它会发生ArgumentException。

答案 2 :(得分:5)

绝对有理由这样做,而且就像大多数例外抛出问题一样,你必须把你当作一个团队中的开发人员来考虑。你正在写的东西可能是另一个系统的一部分,或者它可能是一个库或组件。

如果你编写一个数学库,并且有一个名为Divide(int a, int b)的函数来划分它们,如果其他人想要使用你的方法并传入零,你就会想要抛出一个例外,这样它们就像一个开发人员,知道他们搞砸了。

如果不抛出异常,则会在代码中引入错误。如果我使用了divide方法,并将值10和0放入,这会产生10/0,从而产生异常,唯一正确的答案就是错误。如果您决定更改值以便不发生错误,或者返回0,那不是我所期望的 - 我认为我的部门工作完美,并且从未注意到问题。我可能会把那个0拿去并在其他计算中使用它,不知道这是错误的答案,因为10/0不是0.

答案 3 :(得分:4)

您应该只使用Exception来处理异常情况。

在这种情况下,看起来零将是无效的用户输入。您应该检查无效的用户输入并相应地处理之前,以确定异常是合适的。

只要你正确处理输入,就没有理由发生DivideByZeroException。如果您在验证输入后收到DivideByZeroException,那么您知道您有一个真正的问题(在这种情况下,异常是合适的)。

答案 4 :(得分:3)

如果您正在谈论直接与UI交互的代码,那么没有。我想不出你想要的任何理由。

但是,如果您正在构建其他开发人员使用的类/对象,并且他们传入了明显愚蠢的数据,那么在验证过程中会抛出相应的错误。

答案 5 :(得分:2)

如果您正在编写BigInteger库,那么绝对应该抛出适当的DivideByZero异常。如果你正在写一个购物车库,那么......呃,可能不是。

目前我不能想出抛出NullReferenceException的充分理由。如果您要创建一个API,其文档说明“HummingBirdFeeder.OpenSugarWaterDispenser(Dispenser dispenser, int flowRate)的第一个参数是您要打开的糖水分配器。”如果有人然后出现并将null值传递给此方法,那么你肯定会抛出ArgumentNullException

让你的API NullReferenceException只是懒惰,因为这是错误的,它泄露了你的一些内部。

编辑添加:

既然您已将问题更改为引用ArgumentNullException,那么答案很简单:是的,在这些情况下您绝对应该抛出这种异常:

  • 您正在撰写公开方法。
  • 获取参数的空值在某种程度上是不合适的(即,没有该特定参数,该方法没有意义)。
  • 该方法的文档表明不允许使用空值。

在这种情况下,您的方法应该做的第一件事是检查空值并在违反条件时抛出异常。

如果您正在编写私有或内部方法,那么在大多数情况下,您不需要在发布版本中的运行时验证参数。您可以确保自己的代码正确调用自己的代码。有助于创建该保证的一件事是通过添加断言来验证调试版本中的参数:

Debug.Assert(dispenser != null);

通过这种方式,您可以验证代码是否正常运行并及早捕获任何错误,而不会通过一堆无用的冗余检查来减慢已发布的代码。

答案 6 :(得分:1)

在您自己的代码中,我怀疑会有多大用处。但是,如果您正在编写一个将被其他人使用的库,那么您应该使用异常作为将错误传递回使用您的库的代码的方法。

  

“在框架中,使用了例外   对于硬错误和逻辑错误   错误。起初,它可能很难   接受异常处理作为   报告所有功能的手段   故障。但是,重要的是   设计一个公共方法   报告方法失败的框架   抛出异常。“

Krzysztof Cwalina, Designing Reusable Frameworks

答案 7 :(得分:1)

这里略有误导性的标题,它不是关于抛出(特殊)DivideByZeroException而是提出问题:

  

我应该在验证用户输入时使用异常吗?

之前可能已经提到了这个问题。我的看法:不,只需使用一个流程,让你用错误代码或布尔值来处理这个问题。

但是,在应用程序的更深层验证“数据”时,抛出异常通常是正确的做法。

答案 8 :(得分:1)

如果您正在编写某种形式的数字类并且可以预期调用您的类的代码已经执行了验证,那么我可以看到抛出DivisionByZeroException可能很有用,但在几乎任何其他情况下最好先检查适当的操作和抛出以及ArgumentException或ArgumentOutOfRange异常。

NullReferenceException是框架使用的保留异常之一,您应该永远不会抛出公共API,以及IndexOutOfRange,AccessViolationException和OutOfMemoryException。请参阅“框架设计指南”一书或Code Analysis warning explanation

答案 9 :(得分:0)

没有我能想到的。我只是反对它。例外情况可能很昂贵,因此如果您可以采取防御措施来对付它,那么请执行此操作而不是抛出异常。

至少那是我的高级开发人员告诉我的,当我多次尝试捕捉DivideByZeroException时。

答案 10 :(得分:0)

在开始处理数据之前,最好在函数顶部进行这些检查。而不是在方法中间抛出它们(或任何其他方法抛出这些异常)。

答案 11 :(得分:0)

理论上(也是实践中),识别和避免/消除错误案例比将它们视为例外更好。然而,并不总是可以通过代码测试每个案例或路径 - 它是在每种情况下都不可能控制你的输入。

良好设计的宗旨是让您的程序能够识别并优雅地处理异常情况。此外,最好为您的用户(以及最终自己)提供足够的信息来诊断错误 - 特别是那些部署代码后可能会发生这种情况。因此, 有时会引发异常,例如说明它是否会使您的应用程序代码更健壮,更容易诊断。

答案 12 :(得分:0)

考虑到对于双精度数,除以零实际上会产生一个值:double.Infinity,double.NegativeInfinity或double.NaN,取决于分子分别是正数,负数还是零。

这些值可能已经适合您的情况,如果不是,您可能需要验证输入,并在执行除法之前采取相应的行动。

如果您正在编写API(例如在库上)并希望提供一个不允许除零的合同(比如说它暴露了执行某种除法的方法),那么您可能希望抛出此异常。但通常情况下,我会保留此类异常作为程序错误的指示。

答案 13 :(得分:0)

从不(用户永远不会发送0作为分母)而始终(用户将始终提供适当的参数值)是包含在您的代码中的危险想法。我们只有很小一部分程序,代码永远不会被其他开发人员修改或调用。所以,我们需要编写防御性代码。在除以零的情况下,我不应该决定适当的结果应该是什么,这会落在调用者身上。抛出异常似乎是回避问题的合理方式。虽然涉及费用,但我添加到我的代码中以避免抛出异常的任何基础结构也增加了费用。

答案 14 :(得分:0)

如果您依靠框架来完成工作(.NET或其他),那么您应该让框架抛出异常

这将使您的方法的使用者更容易处理以标准方式抛出的异常。

在除以零的情况下,您只是重新实现相同的逻辑以在框架中抛出异常。

答案 15 :(得分:-1)

从资源的角度来看,抛出异常是件昂贵的事情。你已经阻止了异常发生,为什么抛出一个呢?如果必须告诉用户,请使用一些消息传递机制。如果您需要自己了解它,请记录下来。