我正在清理一些遗留代码,并且发现了显式抛出
NullReferenceException
的方法(例如:检查类的某些属性是否为空或检查配置时)。由于这种类型的异常是由 CLR 在空引用的情况下引发的,因此对于应用程序显式引发的异常来说,这似乎是一个非常糟糕的选择。
我的问题是 - 是否有任何原因使得
NullReferenceException
成为从代码中显式抛出异常的不错选择?
NullReferenceException
的文档暗示您不应该将其从应用程序中丢弃:
请注意,应用程序抛出 ArgumentNullException 异常,而不是此处讨论的 NullReferenceException 异常。
我确信我在其他地方看到过指导(目前找不到任何指南->它在这里https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/using-标准异常类型)您应该避免抛出运行时抛出的异常类型(尽管我将链接到显示运行时抛出“应用程序”异常的内容)
如果您正在检查方法中的属性,那么在继续之前,听起来您可能需要将它们替换为 InvalidOperationException:
InvalidOperationException 用于因参数无效以外的原因导致方法调用失败的情况。
方法调用处于不正确的状态听起来符合这个定义。
不,没有理由抛出
NullReferenceException
。
您总是有一些有关错误原因的更多信息,因此您应该抛出一个传达该信息的异常。
例如,如果您在不允许的情况下获得空引用作为参数,则您将抛出
ArgumentException
或 ArgumentNullException
。
MSDN 是这么说的:
请注意,应用程序会抛出 ArgumentNullException 异常 而不是这里讨论的 NullReferenceException 异常。
所以你的问题的答案可能是“不”。
不,
NullReferenceException
只能由框架本身抛出。 ArgumentNullException
或 InvalidOperationException
是有效的替代方案。
我假设如果代码没有检查,你无论如何都会得到一个 NullReferenceException(NRE),所以不会。但是,我认为应用程序消息可以更好地解释具有 NRE 或 ArgumentExecption 内部异常类型的特定函数的调用机制,因为这是导致问题的潜在问题。
我可以想象一些场景,明确地抛出它是有意义的。我想到的第一个是在 CLR 遇到异常之前完成许多其他处理之前检查属性。
接受的答案确实是正确的,但我认为在最初撰写本文时,MS 尚未提供有关此的明确文档。
明确指出如下:
❌ 不允许公开可调用的 API 显式或隐式抛出 NullReferenceException、AccessViolationException 或 IndexOutOfRangeException。这些异常由执行引擎保留并抛出,在大多数情况下表明存在错误。 进行参数检查以避免抛出这些异常。抛出这些异常会暴露方法的实现细节,这些细节可能会随着时间的推移而改变。