6

假设我有一个扩展方法

public static T TakeRandom<T>(this IEnumerable<T> e)
{
    ...

为了验证论点 e,我应该:

A) if (e == null) throw new NullReferenceException()
B) if (e == null) throw new ArgumentNullException("e")
C) 不检查 e

共识是什么?

我的第一个想法是始终验证参数,因此抛出了 ArgumentNullException。话说回来,既然 TakeRandom() 变成了 e 的一个方法,或许它应该是一个 NullReferenceException。但是如果它是 NullReferenceException,如果我尝试在 TakeRandom() 中使用 e 的成员,无论如何都会抛出 NullReferenceException。

也许我应该使用 Reflector 并找出框架的作用。

4

3 回答 3

11

您应该抛出 ArgumentNullException。您正在尝试进行参数验证,因此应该抛出一个针对参数验证调整的异常。NullReferenceException 不是参数验证异常。这是一个运行时错误。

不要忘记,扩展方法只是底层的静态方法,可以这样调用。虽然在扩展方法上抛出 NullReferenceException 表面上看起来是有意义的,但对于静态方法这样做是没有意义的。无法确定方法中的调用约定,因此 ArgumentException 是更好的选择。

此外,您永远不应该明确抛出 NullReferenceException。这应该只由 CLR 抛出。当显式抛出通常仅由 CLR 抛出的异常时,会出现细微的差异。

这也接近于以下内容的欺骗

于 2009-04-25T04:33:05.873 回答
4

为了与 Enumerable LINQ 运算符保持一致,请抛出 ArgumentNullException(而不是 NullReferenceException)。

我会在 TakeRandom 方法中进行验证,因为堆栈跟踪将清楚地表明它是 TakeRandom 哪些对象被赋予空参数。

于 2009-04-25T04:21:56.540 回答
1

也许我疯了,但既然这是一个论点,我会抛出一个 ArgumentNullException :/

不过,一般的经验法则是尽可能抛出派生自 System.ApplicationException 的异常。NullReferenceException 是框架/CLR 会抛出的东西。

http://msdn.microsoft.com/en-us/library/system.exception(VS.71).aspx

基类 Exception 下存在两类异常:

从 SystemException 派生的预定义公共语言运行时异常类。从 ApplicationException 派生的用户定义的应用程序异常类。

于 2009-04-25T07:17:23.670 回答