【问题标题】:Throwing exception vs checking null, for a null argument为空参数抛出异常与检查空值
【发布时间】:2010-03-26 21:53:46
【问题描述】:

如果参数为空(例如 if (a is null) throw new ArgumentNullException()),哪些因素决定抛出异常,而不是事先检查参数是否为空。

我不明白为什么应该抛出异常而不是首先检查 null?抛出异常方法有什么好处?

这适用于 C#/.NET

谢谢

【问题讨论】:

  • 当您说事先检查参数时,您能否澄清一下您的意思?你想让调用者检查 null 吗?

标签: c# .net exception ado.net


【解决方案1】:

通常,当一个参数被传递时,你会抛出 ArgumentNullException,其值为 null,但“永远”不应为 null。它是用于处理空值的特定 ArgumentException。

通常,如果您知道您将获取空值作为 args,您会检查空值并相应地计划您的方法的其余部分 - 如果不存在记录,通常会创建记录,或者执行与执行不同的子例程'如果存在有效参数,则运行。在这种情况下,我通常不使用 ArgumentNullException,因为我计划将 null 作为有效输入。

我只使用 ArgumentNullException,当我确定某些东西到达那里时不应该为空,并且我想记下一个定义为“无效”的参数。

【讨论】:

  • 有任何真实世界的例子吗?谢谢。
  • 我通常使用的示例是 asp.net 解决方案中的页面,该页面只能通过另一个页面中的链接访问,并且需要存在特定的请求参数。我总是假设它不会为空,但通常有一个业务用户认为手动输入该网址以“更快”到达那里,不了解处理页面上的代码需要什么 - 在这种情况下,我会在要求该请求参数存在的方法中抛出一个参数nullexception。
【解决方案2】:

当参数为空时,您的方法可以执行以下三种操作之一。它可以抛出异常,它可以不做任何事情就返回,或者它可以做出假设并尝试继续。我假设您正在尝试在前两个选项之间进行选择。

由于调用方法始终可以在调用您的方法之前检查参数,因此可以防止传递无效值。无论您的方法如何处理无效值,这都是正确的。

当使用无效参数调用您的方法时,它应该通知调用者处理没有继续。您可以通过抛出异常或返回错误值来通知它。如果您检查 null 并且不返回错误值,则调用方法将假定您的方法已正确处理。

您希望调用方法如何处理您的方法未处理的情况?如果传递 null 是一种正常情况,并且应该可以通过调用方法轻松处理,则在 null 参数上返回错误是可以接受的。在这种情况下,调用方法要么检查之前的参数,要么检查之后的返回值,这取决于编写调用方法的人。

如果传递 null 非常罕见,则抛出异常。调用方法可以通过在调用方法之前检查参数来防止异常,就像上面一样。通过抛出异常,调用堆栈可以展开,而无需添加大量代码。

总结:
如果设置为 null 的参数是例行程序,并且应该编写调用方法来处理您的函数返回而不做任何事情,则只返回一个错误值。如果 null 参数很少见,并且调用方法无法处理您的方法,则什么都不做会引发异常,因此调用堆栈被展开。

【讨论】:

    【解决方案3】:

    永远不要编写检查空参数然后什么都不做的代码。在客户端代码中隐藏错误是非常错误的,当您的 API 没有被正确使用时,您希望尽可能提供帮助。

    ArgumentNullException 非常很有帮助。

    【讨论】:

    • 将 Null 参数视为例如当且仅当这是合同规定的人会做的事情时,一个空列表是合适的。某些 .net 方法确实可以做到这一点(例如 Delegate.Combine)。
    【解决方案4】:

    作为方法编写者,您必须决定是否可以合理地推断调用者可能通过null 表达的意思。如果可以,请采取行动。如果不能,请抛出ArgumentNullException 通知调用者他们给了你一个你不能使用的值。

    这是防御性编程 - 尽可能早地死掉,而不是试图在部分有效的状态下跛行,这会变成更微妙(也更难修复)的错误。

    【讨论】:

      【解决方案5】:

      这是关于确定您的方法的合同是什么。如果您希望合同规定调用者不得传入null,则必须在收到异常时抛出异常。不要相信来电者永远不会犯那个错误! OTOH,如果您希望合同在该论点中不那么严格(无论这意味着什么;要么优雅地什么都不做,要么采取其他某种行为),那么例外显然是错误的。

      无论你做什么,记录它。在向您的方法扔东西之前,让可怜的调用者有机会纠正它...

      【讨论】:

        猜你喜欢
        • 2019-12-15
        • 1970-01-01
        • 1970-01-01
        • 2010-12-02
        • 2016-05-22
        • 1970-01-01
        • 2017-09-02
        • 2012-09-09
        • 2015-09-25
        相关资源
        最近更新 更多