代码之家  ›  专栏  ›  技术社区  ›  Callum Watkins

何时为空检查启用了可空引用类型的参数

  •  4
  • Callum Watkins  · 技术社区  · 7 年前

    给定一个使用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的一部分,因此我怀疑这些检查可能是多余的。这两个参数没有标记为可以为空,因此如果任何调用代码可能传入空值,编译器应该发出警告。

    1 回复  |  直到 7 年前
        1
  •  6
  •   Jon Skeet    7 年前

    给定一个使用C 8.0的可空引用类型特性的程序中的函数,我是否仍要对参数执行空检查?

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

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

    在这里 FooImpl 不是公共API的一部分,但如果 Foo 不验证 它的 参数。(事实上,它可能依赖于 执行参数验证。)

    签入 足印 当然不是 冗余 它在执行时执行检查 不能 在编译时要绝对确定。可以为空的引用类型提高了一般安全性,更重要的是 表现力 代码,但它们与clr提供的类型安全不同(阻止您处理 string 作为参考 Type 例如,引用)。编译器在执行时查看某个特定表达式是否为空时有多种“错误”的方式,编译器可以用 ! 不管怎样。

    更广泛地说:如果你的支票不是多余的 之前 C 8,它们不是多余的 之后 C 8,因为可以为空的引用类型功能不会更改为代码生成的IL,而不是属性。

    因此,如果您的公共API正在执行所有适当的参数检查( 在上面的示例中),那么签入代码已经是多余的。你对此有多自信?如果你绝对有信心,而且错误的影响很小,那么肯定——去掉验证。C 8功能可能会帮助您获得信心,但您仍然需要小心,不要 毕竟,上面的代码不会给出任何警告。

    就我个人而言,在更新c_8的noda时间时,我不会删除任何参数验证。