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


10

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

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

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

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


public void Foo(string test){...}还是public Foo(string test){...}
humpty duMpty

谢谢,我已经解决了。那就是当人过多地依赖R#生成构造函数时发生的事情:)
Ilya Chernomordik

2
C#9将(可能)添加简化的null验证
史蒂文,

简而言之,“可空引用类型”功能被完全破坏了。
亚历杭德罗

Answers:



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;}
}

是的,您是对的,无论如何,这只是警告。我希望将来他们真的可以像Kotlin
Ilya Chernomordik

2

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

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

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

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

当然,人们仍然可以使用反射来将您的代码f ***起来,但是随后它们就可以了


因此,这实际上意味着即使我使用了非可空类型,我仍然可以获得Null引用异常,对吗?
伊利亚·切尔诺蒙迪克

嗯...。无法在编译的代码中使用cos,因为您有提示...但是其他人的代码却没有提示,但是引用了您的代码-是的,他们可以得到null异常
米尔尼

好吧,例如,如果一个自动映射器使用了您的构造函数,或者类似的东西,那么仍然是您会得到异常的:)
Ilya Chernomordik

Of course people can still use reflection to f*** your code up,真实,真实。您绝对可以使用反射来执行此操作,是否建议这样做,,还是有人继续这样做,是的。
Çöđěxěŕ

2

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


-1

为了处理空检查,并使代码可读,我建议使用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()  
    { }  
}  

无法避免出现空值,但是可以对其进行彻底检查。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.