Nullable Reference Types(NRT),是在C# 8(.net core3.1)引入C#的一个重要的功能,并且在C#10(.NET6)中默认开启。
在代码中最直观的改动就是引入了“?”, 你可以使用string?, int?等等来代表一个类型可为空。当然对于值类型来说,?其实是Nullable<T>的语法糖,比如int?本质的类型就是Nullable<int>。这时候 int? a = null;的操作也是可以成立的
可能一开始很多人都没有理解这个功能的本质,只会觉得,怎么我的项目一到.NET6突然多了一堆波浪号警告,或是认为这个类型好像只对一些值类型管用,毕竟引用类型本来就是可以为null嘛,加个?有什么用,还麻烦。
这么理解其实也不算完全错误。是的,NRT为值类型引入了可空的值,这是一项最容易被理解的功能,当然也是非常实用的功能之一。不过这并不是NRT真正面对的敌人
![]()
NRT真正想要解决的是null这个恶魔会引发的灾难,NullReferenceException(NRE)
NRE一直都是许多编程者们的噩梦,稍有不注意,他就会隐藏在代码之中。成为一颗随时会爆炸的地雷。现在也有非常多的人认为,Null本身就不该存在在语言之中,他就是一个纯粹的恶魔,毒药。
C#作为一个老牌,稳定(也许不那么稳定(笑))了许久的语言,自然已经没有选择"大刀阔斧的直接砍掉null"的余地,他引入了NRT这个功能。
我们需要了解的是,启用NRT有一个深层含义,其意味着一个语义的反转。这也是造成当项目启用NRT之后,往往能看到漫天报警的原因。
引用类型默认为可空 -> 需要显式标记引用类型可为空
这也许会觉得看起来没什么,但事实上意义重大。代码现在能以显式的方式告诉编程者,或是编译器,这个类型可不可为空。
事实上启用了#nullable(NRT)并不会影响引用类型设置为null(即使没有任何标记,你还是可以将他设置为null),这其实有点语义上的错位,启用了NRT后事实上反而是不允许未标记可为空的类型,设置为null。
经过了上述的改动后。现在我们再来看我们的代码。我们已经明确的知晓了,我们代码中哪些参数,变量可为空。而不像以前一样,所有引用类型都为空。
在拥有NRT之前,我们必须要手动的校验所有引用类型的参数或是变量,才可以确保不会被恶魔NRE,以未知的方式在代码中抛出错误。而现在,我们把这个隐患暴露在了阳光之下,引用类型应当默认不可为空(从此处出发,读者可以想想,变量是否也应该"不变"? ),所有可空类型,必须要向我们报告,他是可空的。
这样有两个好处,其一是我们可以不必再对所有的引用类型去做判空处理,当然,这个还不够。因为事实上还是可以传入null。其二则是编译器可以代替我们检查,哪里的代码,有被NRE恶魔侵扰的隐患。所以漫天的报警(当然这些报警的行为也是在不断优化的,现在会好不少),其实都是一些大大小小的隐患,应该要去正确的声明他,或是让他拥有该有的值。
配合??=运算符(当变量为空则等于),以及damnit运算符(!,用来显示告诉编译器该变量不为空,常用于编译器无法推断,或是手动测试null的情况时使用)可以更好的使用NRT功能。
测试代码如下,可以放到ide中看看有什么报警吧~
// See https://aka.ms/new-console-tesmplate for more information
string a = null;
string? c = String.Empty;
c = a;
Test("");
Test(c);
Test(a);
Test(null);
Test(null!);
return;
void Test(string b)
{
Console.WriteLine(b);
}
void Test1(string? b)
{
Console.WriteLine(b.Length);
b ??= string.Empty;
Console.WriteLine(b.Length);
}

视频链接: Nullable Reference Types(NRT)为什么会出现在C#之中?_哔哩哔哩_bilibili
公众号搜索:scixing的炼丹房

1357

被折叠的 条评论
为什么被折叠?



