【发布时间】:2010-03-26 21:53:46
【问题描述】:
如果参数为空(例如 if (a is null) throw new ArgumentNullException()),哪些因素决定抛出异常,而不是事先检查参数是否为空。
我不明白为什么应该抛出异常而不是首先检查 null?抛出异常方法有什么好处?
这适用于 C#/.NET
谢谢
【问题讨论】:
-
当您说事先检查参数时,您能否澄清一下您的意思?你想让调用者检查 null 吗?
如果参数为空(例如 if (a is null) throw new ArgumentNullException()),哪些因素决定抛出异常,而不是事先检查参数是否为空。
我不明白为什么应该抛出异常而不是首先检查 null?抛出异常方法有什么好处?
这适用于 C#/.NET
谢谢
【问题讨论】:
通常,当一个参数被传递时,你会抛出 ArgumentNullException,其值为 null,但“永远”不应为 null。它是用于处理空值的特定 ArgumentException。
通常,如果您知道您将获取空值作为 args,您会检查空值并相应地计划您的方法的其余部分 - 如果不存在记录,通常会创建记录,或者执行与执行不同的子例程'如果存在有效参数,则运行。在这种情况下,我通常不使用 ArgumentNullException,因为我计划将 null 作为有效输入。
我只使用 ArgumentNullException,当我确定某些东西到达那里时不应该为空,并且我想记下一个定义为“无效”的参数。
【讨论】:
当参数为空时,您的方法可以执行以下三种操作之一。它可以抛出异常,它可以不做任何事情就返回,或者它可以做出假设并尝试继续。我假设您正在尝试在前两个选项之间进行选择。
由于调用方法始终可以在调用您的方法之前检查参数,因此可以防止传递无效值。无论您的方法如何处理无效值,这都是正确的。
当使用无效参数调用您的方法时,它应该通知调用者处理没有继续。您可以通过抛出异常或返回错误值来通知它。如果您检查 null 并且不返回错误值,则调用方法将假定您的方法已正确处理。
您希望调用方法如何处理您的方法未处理的情况?如果传递 null 是一种正常情况,并且应该可以通过调用方法轻松处理,则在 null 参数上返回错误是可以接受的。在这种情况下,调用方法要么检查之前的参数,要么检查之后的返回值,这取决于编写调用方法的人。
如果传递 null 非常罕见,则抛出异常。调用方法可以通过在调用方法之前检查参数来防止异常,就像上面一样。通过抛出异常,调用堆栈可以展开,而无需添加大量代码。
总结:
如果设置为 null 的参数是例行程序,并且应该编写调用方法来处理您的函数返回而不做任何事情,则只返回一个错误值。如果 null 参数很少见,并且调用方法无法处理您的方法,则什么都不做会引发异常,因此调用堆栈被展开。
【讨论】:
永远不要编写检查空参数然后什么都不做的代码。在客户端代码中隐藏错误是非常错误的,当您的 API 没有被正确使用时,您希望尽可能提供帮助。
ArgumentNullException 非常很有帮助。
【讨论】:
作为方法编写者,您必须决定是否可以合理地推断调用者可能通过null 表达的意思。如果可以,请采取行动。如果不能,请抛出ArgumentNullException 通知调用者他们给了你一个你不能使用的值。
这是防御性编程 - 尽可能早地死掉,而不是试图在部分有效的状态下跛行,这会变成更微妙(也更难修复)的错误。
【讨论】:
这是关于确定您的方法的合同是什么。如果您希望合同规定调用者不得传入null,则必须在收到异常时抛出异常。不要相信来电者永远不会犯那个错误! OTOH,如果您希望合同在该论点中不那么严格(无论这意味着什么;要么优雅地什么都不做,要么采取其他某种行为),那么例外显然是错误的。
无论你做什么,记录它。在向您的方法扔东西之前,让可怜的调用者有机会纠正它...
【讨论】: