.NET 源码学习 [数据结构-线性表1.2] 链表与 LinkedList<T>( 九 )


仅当左操作数的计算结果为 null 时,Null 合并赋值运算符 ??= 才会将其右操作数的值赋值给其左操作数 。如果左操作数的计算结果为非 null,则 ??= 运算符不会计算其右操作数 。其中 ??= 运算符的左操作数必须是变量、属性或索引器元素 。
举例如下:

.NET 源码学习 [数据结构-线性表1.2] 链表与 LinkedList<T>

文章插图
此时 a 为 null,因此返回 5
—— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— ——
.NET 源码学习 [数据结构-线性表1.2] 链表与 LinkedList<T>

文章插图
此时 a 不为 null,因此返回 a 的值 。
—— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— ——
.NET 源码学习 [数据结构-线性表1.2] 链表与 LinkedList<T>

文章插图

.NET 源码学习 [数据结构-线性表1.2] 链表与 LinkedList<T>

文章插图
同理可得,a 为空返回11;a 不为空返回 a 。
五、可空容忍 !
.NET 源码学习 [数据结构-线性表1.2] 链表与 LinkedList<T>

文章插图
其实这是一个补充,在代码中如果我们判断出某个变量在使用时一定不为null,但是编译器会在可空上下文中抛出警告,这是一个不太正常的行为,可空容忍可以消除这种警告,将不可为空的引用类型转换成可为空的引用类型 。
.NET 源码学习 [数据结构-线性表1.2] 链表与 LinkedList<T>

文章插图

.NET 源码学习 [数据结构-线性表1.2] 链表与 LinkedList<T>

文章插图
假如我们知道 obj 和 obj.ToString() 在这里一定不为空,那么就可以在 obj 与 ToString() 的结果后加上可空容忍运算符,将其转换为不可空类型,以此消除警告 。
.NET 源码学习 [数据结构-线性表1.2] 链表与 LinkedList<T>

文章插图
这样操作后,obj 不可再被赋值为 null 。
六、更多的可空特性【注:
1.     特性一般用来解决警告问题,并不能解决错误或进行强制类型转换 。
2.     特性的修饰更多地,只起到标识告知的作用 。】
需要引入命名空间
.NET 源码学习 [数据结构-线性表1.2] 链表与 LinkedList<T>

文章插图
(一) AllowNull性质:前置条件,即放在修饰对象前 。
作用:将不可为 null 的参数、字段或属性使其可以为 null 。【注意,这里的“不可为”指的是警告内容,不是数据类型上的不可为空】
举例:
.NET 源码学习 [数据结构-线性表1.2] 链表与 LinkedList<T>

文章插图
现在有一个字段,当通过属性获取字段值的时候,一定不会获得到 null,因为在 set 里面指定了非 null 的默认值 。然而在方法 Set() 里是允许设置 null 到这个属性,但属性 Msg 是不可为空的 。于是,为了解决警告的出现,要么将字段定义为可空,要么将这个加上特性 [AllowNull] 。这样,获取此字段的时候会得到非 null 值,但设置的时候却可以传递 null 。
.NET 源码学习 [数据结构-线性表1.2] 链表与 LinkedList<T>

文章插图

.NET 源码学习 [数据结构-线性表1.2] 链表与 LinkedList<T>

文章插图
即,将不可为空的属性 Msg 标记为可为空(可以传入空值),但传入空时会保持其默认值 。
大多数情况下,属性或 in、out 和 ref 参数需要此特性 。当变量通常为非 null 时,[AllowNull] 是最佳选择,但需要允许 null 作为前提条件 。

经验总结扩展阅读