Jon*_*eet 146
是的,有充分的理由:
NullReferenceException
至于你的反对意见:
并为你的断言:
显然,使用s的代码无论如何都会抛出异常.
真?考虑:
void f(SomeType s)
{
// Use s
Console.WriteLine("I've got a message of {0}", s);
}
Run Code Online (Sandbox Code Playgroud)
这用s
,但它没有抛出异常.如果它为s
null无效,并且表明出现了错误,则异常是最合适的行为.
现在,在那里你把这些参数验证检查,则是另一回事.您可能决定信任自己类中的所有代码,因此不必担心私有方法.您可能决定信任组件的其余部分,因此不必担心内部方法.您几乎肯定会验证公共方法的参数.
旁注:单参数构造函数重载ArgumentNullException
应该只是参数名,所以你的测试应该是:
if (s == null)
{
throw new ArgumentNullException("s");
}
Run Code Online (Sandbox Code Playgroud)
或者你可以创建一个扩展方法,允许有点terser:
s.ThrowIfNull("s");
Run Code Online (Sandbox Code Playgroud)
在我的(通用)扩展方法的版本中,如果它为非null,我会返回原始值,允许您编写如下内容:
this.name = name.ThrowIfNull("name");
Run Code Online (Sandbox Code Playgroud)
如果您对此不太感兴趣,也可以使用不带参数名称的重载.
Eri*_*ert 47
我同意乔恩,但我会补充一点.
我对何时添加显式空检查的态度是基于以下前提:
throw
陈述是陈述.if
一个陈述的后果.throw
在if (x == null) throw whatever;
如果没有可能的方法来执行该语句,则无法对其进行测试,应将其替换为Debug.Assert(x != null);
.
如果有可能的方法来执行该语句,那么编写语句,然后编写一个单元测试来执行它.
这是特别是公共类型的公共方法,检查他们的论点以这种方式很重要; 你不知道你的用户会做什么疯狂的事情.给他们"嘿,你笨蛋,你做错了!" 尽快例外.
相反,私有类型的私有方法更可能出现在您控制参数的情况下,并且可以强有力地保证参数永远不为空; 使用断言来记录该不变量.
如果没有一个明确的if
检查,它可以是很难搞清楚什么是null
,如果你没有自己的代码.
如果您NullReferenceException
从没有源代码的库中深入了解,那么您可能很难弄清楚您做错了什么.
这些if
检查不会使您的代码明显变慢.
请注意,ArgumentNullException
构造函数的参数是参数名称,而不是消息.
你的代码应该是
if (s == null) throw new ArgumentNullException("s");
Run Code Online (Sandbox Code Playgroud)
我编写了一个代码片段来简化这个过程:
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Check for null arguments</Title>
<Shortcut>tna</Shortcut>
<Description>Code snippet for throw new ArgumentNullException</Description>
<Author>SLaks</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
<SnippetType>SurroundsWith</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>Parameter</ID>
<ToolTip>Paremeter to check for null</ToolTip>
<Default>value</Default>
</Literal>
</Declarations>
<Code Language="csharp"><![CDATA[if ($Parameter$ == null) throw new ArgumentNullException("$Parameter$");
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
Run Code Online (Sandbox Code Playgroud)
我已经使用了一年了:
_ = s ?? throw new ArgumentNullException(nameof(s));
Run Code Online (Sandbox Code Playgroud)
这是一个单行,而throw(_
)表示没有不必要的分配。