C#8中的不可为空的引用类型在运行时是否可以为null?

时间:2019-12-30 12:41:56

标签: c# c#-8.0 non-nullable

在我看来,真的不能保证非空变量永远不会为空。想象一下,我有一个具有不为空的属性的类:

public class Foo
{
    public Foo(string test)
    {
        Test = test;
    }
    public string Test {get;set;}
}

现在看来现在不能为null。但是,如果我们用另一个不使用可为空的上下文的库引用该类,则不会阻止它在其中发送null。

是正确的还是有一些运行时检查,也许可以确保做到这一点?

5 个答案:

答案 0 :(得分:2)

您是正确的,其他未使用新功能的代码可以为此属性分配null,没有运行时检查,它只是编译器提示。

如果要进行运行时检查,可以随时自己做:

public string Test { get; set{ if (value == null) throw new ArgumentNullException() } }

请注意,您可以保证在代码的大部分中不为空,您只需向顶级公共API添加防护,并确保适当密封了类,等等。

当然,人们仍然可以使用反射功能来使您的代码失效,但是随后它就会出现在它们上

答案 1 :(得分:2)

这是MS对(https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/upgrade-to-nullable-references#interfaces-with-external-code)的评价:

  

即使您的代码是在启用了可空注释上下文的情况下编译的,编译器也无法验证对公共API的所有调用。此外,尚未选择使用可空引用类型的项目可能会占用您的库。验证公共API的输入,即使您已将其声明为非空类型。

答案 2 :(得分:2)

某人可以永远做

var myFoo = new Foo(null);

也许您可以使用域驱动设计

public class Foo
{
    public Foo(string test)
    {
         if (string.IsNullOrWhiteSpace(test))
             throw new ArgumentNullException(nameof(test));

         Test = test;
    }
    public string Test {get;private set;}
}

答案 3 :(得分:1)

即使在您自己的代码中,如果您选择这样做,也可以使用允许为null的运算符传递null。就编译器的可空性分析而言,null!被认为不是非空的。

答案 4 :(得分:0)

要处理null检查并使代码可读,我建议使用Null Object Design模式。

更多阅读此处:

https://www.c-sharpcorner.com/article/null-object-design-pattern/

基本上,它涉及创建一个新对象,该对象从相同的接口派生并具有空实例。

示例:

public class NullExample : IExample  
{  
    private static NullExample _instance;  
    private NullExample()  
    { }  

    public static NullExample Instance  
    {  
        get {  
            if (_instance == null)  
                return new NullExample();  
            return _instance;  
        }  
    }  

    //do nothing methods  
    public void MethodImplementedByInterface1()  
    { }  

    public void MethodImplementedByInterface1()  
    { }  
}  

不能避免使用null,但是可以对其进行彻底检查。