本文介绍了何时对启用了可空引用类型的参数进行空检查的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Given a function in a program using C# 8.0's nullable reference types feature, should I still be performing null checks on the arguments?

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,则编译器应发出警告.

None of the code is part of a public API so I suspect that these checks may be redundant. The two parameters are not marked as nullable, so the compiler should warn if any calling code may be passing in null.

推荐答案

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

That depends on how certain you are of all the paths through your API. Consider this code:

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

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

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

Here FooImpl isn't part of the public API, but can still receive a null reference if Foo doesn't validate its parameter. (Indeed, it may be relying on Foo to perform argument validation.)

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

Checking in FooImpl is certainly not redundant in that it's performing checks at execution time that the compiler cannot be absolutely certain about at compile-time. Nullable reference types improve the general safety and more importantly the expressiveness of code, but they're not the same kind of type safety that the CLR provides (to stop you treating a string reference as a Type reference, for example). There are various ways the compiler can be "wrong" about its view of whether or not a particular expression might be null at execution time, and the compiler can be overridden with the ! anyway.

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

More broadly: if your checks weren't redundant before C# 8, they're not redundant after C# 8, because the nullable reference type feature doesn't change the IL generated for the code other than in terms of attributes.

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

So if your public API was performing all the appropriate parameter checking (Foo in the example above) then the checking in the code was already redundant. How confident are you of that? If you're absolutely confident and the impact of being wrong is small, then sure - get rid of the validation. The C# 8 feature may help you gain confidence in that, but you still need to be careful you don't get too confident - after all - the code above would give no warnings.

我个人并没有在更新C#8的Noda Time时删除任何参数验证.

Personally I'm not removing any parameter validation when updating Noda Time for C# 8.

这篇关于何时对启用了可空引用类型的参数进行空检查的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 19:46