何时对启用了可空引用类型的参数进行空检查

时间:2019-02-05 01:25:04

标签: c# nullable c#-8.0

给出使用C#8.0的可为空的引用类型功能的程序中的函数,我是否仍应对参数执行空值检查?

void Foo(string s, object o)
{
    if (s == null) throw new ArgumentNullException(nameof(s)); // Do I need these?
    if (o == null) throw new ArgumentNullException(nameof(o));
    ...
}

这些代码都不是公共API的一部分,因此我怀疑这些检查可能是多余的。这两个参数未标记为可为空,因此,如果有任何调用代码可能传入null,则编译器应发出警告。

1 个答案:

答案 0 :(得分:7)

  

给出使用C#8.0的可为空的引用类型功能的程序中的函数,我是否仍应对参数执行空值检查?

这取决于您对通过API的所有路径的确定性。考虑以下代码:

public void Foo(string x)
{
    FooImpl(x);
}

private void FooImpl(string x)
{
    ...
}

此处FooImpl不是公共API的一部分,但是如果Foo不验证参数,仍可以收到空引用。 (实际上,可能依靠Foo来执行参数验证。)

签入FooImpl当然不是多余,因为它在执行时执行检查,使编译器不能在编译时绝对确定。可空的引用类型提高了常规安全性,更重要的是提高了代码的 expressiveness ,但它们与CLR提供的类型安全性不同(停止将string引用视为Type引用)。对于特定表达式在执行时是否为null的看法,编译器有多种“错误”的看法,而且无论如何,编译器都可以用!覆盖。

更广泛的说:如果您的检查在C#8之前不是多余的,则它们在C#8之后的也不是多余的,因为可空引用类型功能不会改变为代码生成的IL,而不是根据属性生成的。

因此,如果您的公共API正在执行所有适当的参数检查(上例中为Foo),则代码中的检查已经是多余的。您对此有多自信?如果您绝对有信心,并且犯错的影响很小,那么可以确定-摆脱验证。 C#8功能可以帮助您增强对此的信心,但是您仍然需要小心,不要让充满信心-毕竟-上面的代码不会给出警告。

就C#8更新Noda Time而言,我个人并没有删除任何参数验证。