代码之家  ›  专栏  ›  技术社区  ›  Armstrongest

是否有任何理由引发DivideByZeroException?

  •  21
  • Armstrongest  · 技术社区  · 15 年前

    有什么好主意的时候 throw 可以避免的错误?

    我特别想的是 DivideByZeroException ArgumentNullException

    例如:

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

    有没有什么理由像这样抛出错误?

    注: 我不是在说 吸引人的 这些错误,特别是在知道是否有好的理由扔他们。

    只是重申一下 :

    我知道在我给出的示例中,处理错误可能会更好。也许这个问题应该换个说法。有什么理由 其中一个错误,而不是在 位置。

    16 回复  |  直到 15 年前
        1
  •  20
  •   juharr    15 年前

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

        2
  •  12
  •   Hans Passant    15 年前

    .NET运行时已经非常擅长抛出这些异常。它们还高度描述了什么是错误的,您不能在异常消息中添加任何好的注释。”你不能被零除“不加任何值。

    但是,您可以通过筛选客户机代码传递的值来避免这些异常。如果客户机代码传递了一个空值,您将需要参数名为argumentNullException的参数,当它传递了一个易于trip divideByZero的对象时,您将需要argumentNullException。

        3
  •  5
  •   NibblyPig    15 年前

    这绝对是有原因的,而且和大多数抛出问题的例外情况一样,您必须将自己视为一个团队中的开发人员。您正在编写的内容可能是其他系统的一部分,也可能是库或组件。

    如果你写了一个数学库,并且有一个函数 Divide(int a, int b) 这将它们分开,如果有人想使用您的方法并传入零,那么您将需要抛出一个异常,这样,作为开发人员,他们就会知道他们搞砸了。

    如果不抛出异常,则会在代码中引入错误。如果我使用了你的除法,把值10和0放进去,这会产生10/0,因此是一个例外,唯一正确的答案就是错误。如果您决定更改这些值,这样就不会发生错误,或者返回0,这不是我所期望的——我假设我的除法工作得很好,而且从未注意到任何问题。我可能会取这个0,然后在其他计算中使用它,不知道这是错误的答案,因为10/0不是0。

        4
  •  4
  •   Justin Niessner    15 年前

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

    在这种情况下,零可能是无效的用户输入。您应该检查无效的用户输入并进行相应的处理。 以前 你会发现一个例外是适当的。

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

        5
  •  3
  •   CResults    15 年前

    如果你说的是直接与用户界面交互的代码,那么不,我想不出任何你想要的理由。

    但是,如果您正在构建一个被其他开发人员使用的类/对象,并且这些开发人员已经传递了明显愚蠢的数据,那么在验证期间抛出适当的错误。

        6
  •  2
  •   Jeffrey L Whitledge    15 年前

    如果您正在编写一个BigInteger库,那么您绝对应该抛出一个适当的 DivideByZero 例外。如果你正在写一个购物车库,那么……嗯,也许不是。

    我现在想不出一个好理由 NullReferenceException . 如果您使用文档创建了一个api,其中说明“ HummingBirdFeeder.OpenSugarWaterDispenser(Dispenser dispenser, int flowRate) 是你想要打开的糖饮水机。”如果有人来给这个方法传递一个空值,那么你一定要抛出一个 ArgumentNullException .

    空引用异常 然而,从你的API中得到的只是懒散,因为那是错误的,它泄漏了你的一些内部信息。

    编辑添加:

    现在你把问题改成 ArgumentNullException 那么答案很简单:是的,在这种情况下,您肯定应该抛出这种异常:

    • 您正在编写公共方法。
    • 获取参数的空值在某种程度上是不合适的(即,如果没有该特定参数,该方法就没有意义)。
    • 方法的文档指示不允许空值。

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

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

    Debug.Assert(dispenser != null);
    

    通过这种方式,您可以验证代码是否正常工作,并在早期捕获任何错误,而不必通过一系列无用的、冗余的检查来减慢释放的代码的速度。

        7
  •  1
  •   Dan Diplo    15 年前

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

    “在框架中,使用异常 对于硬错误和逻辑错误 错误。起初,这可能很困难 将异常处理作为 报告所有功能的方法 失败。但是,重要的是 设计的所有公共方法 报告方法失败的框架 引发异常。“

    Krzysztof Cwalina, Designing Reusable Frameworks

        8
  •  1
  •   Henk Holterman    15 年前

    这里稍微有点误导性的标题,它不是关于抛出(特殊)divideByZeroException,而是关于以下问题:

    在验证用户输入时是否应使用异常?

    这可能是以前问过的。我的看法是:不,只需要使用一个可以让您用错误代码或布尔值处理这个问题的流。

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

        9
  •  1
  •   Ian G    15 年前

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

    NullReferenceException是框架使用的保留异常之一,您不应通过公共API以及IndexOutOfRange、AccessViolationException和OutOfMemoryException抛出这些异常。参见框架设计指南手册或 Code Analysis warning explanation

        10
  •  0
  •   Jack Marchetti    15 年前

    没有我能想到的。我只是计划反对它。异常可能很昂贵,因此如果您可以防御性地对其进行编程,请执行该操作,而不是抛出异常。

    至少这是我的高级开发人员告诉我的,当我在许多月前试图捕捉一个除数为零的例外。

        11
  •  0
  •   ata    15 年前

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

        12
  •  0
  •   LBushkin    15 年前

    在理论上(和实践上),识别和避免/消除错误案例比将它们作为例外对待要好。 但是,不可能总是通过代码测试每个案例或路径——也不可能在每个案例中控制输入。

    良好设计的一个原则是让程序识别并优雅地处理异常情况。 此外,最好为您的用户(最终是您自己)提供足够的信息来诊断错误,尤其是在部署代码之后可能发生的错误。因此,它 有时抛出异常(如该类)是有意义的,因为它会使应用程序代码更健壮,更容易诊断。

        13
  •  0
  •   cdkMoose    15 年前

    从未 (用户将永远不会发送0作为分母)和 总是 (用户将始终提供适当的参数值)是包含在代码中的危险思想。只有很小比例的美国程序,代码永远不会被其他开发人员修改或调用。所以,我们需要编写防御代码。在除数为零的情况下,我不应该决定什么是适当的结果,这会影响到调用方。抛出异常似乎是一种将问题退回的合理方法。虽然涉及到开销,但是我添加到代码中以避免引发异常的任何基础设施也会增加开销。

        14
  •  0
  •   Paul Ruane    15 年前

    考虑到对于双精度数,除以零实际上会产生一个值:double.infinity、double.negative infinity或double.nan,这取决于分子是正的、负的还是零。

    可能这些值已经适合您的情况,如果不适合,您可能希望在执行除法之前验证输入并相应地执行操作。

    如果您正在编写API(例如在库中),并且希望提供一个不允许零除的协定(例如它公开了执行某种除法的方法),那么您可能希望抛出此异常。不过,通常情况下,我会保留这种类型的异常作为编程错误的指示器。

        15
  •  0
  •   Even Mien    15 年前

    如果您依赖一个框架来完成这项工作(.net或其他),那么您应该 让框架抛出异常 .

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

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

        16
  •  -1
  •   Daniel Dyson    15 年前

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

    推荐文章