在我看来,真的不能保证非空变量永远不会为空。想象一下,我有一个具有不为空的属性的类:
public class Foo
{
public Foo(string test)
{
Test = test;
}
public string Test {get;set;}
}
现在看来现在不能为null。但是,如果我们用另一个不使用可为空的上下文的库引用该类,则不会阻止它在其中发送null。
是正确的还是有一些运行时检查,也许可以确保做到这一点?
答案 0 :(得分:2)
您是正确的,其他未使用新功能的代码可以为此属性分配null,没有运行时检查,它只是编译器提示。
如果要进行运行时检查,可以随时自己做:
public string Test { get; set{ if (value == null) throw new ArgumentNullException() } }
请注意,您可以保证在代码的大部分中不为空,您只需向顶级公共API添加防护,并确保适当密封了类,等等。
当然,人们仍然可以使用反射功能来使您的代码失效,但是随后它就会出现在它们上
答案 1 :(得分:2)
即使您的代码是在启用了可空注释上下文的情况下编译的,编译器也无法验证对公共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,但是可以对其进行彻底检查。