第 19 章 可空值类型
第 19 章 可空值类型
NyxX第 19 章 可空值类型
本章内容
现在,要在代码中使用一个可空的 Int32,就可以像下面这样写:
1 | Nullable<Int32> x = 5; |
编译并运行上述代码,将获得以下输出:
1 | x: HasValue=True, Value=5 |
19.1 C#对可空值类型的支持
C# 允许用问号表示法来声明并初始化 x 和 y 变量:
1 | Int32? x = 5; |
在 C#中, Int32? 等价于 Nullable<Int32>。但 C# 在此基础上更进一步,允许开发人员在可空实例上执行转换和转型①。C# 还允许向可空实例应用操作符。以下代码对此进行了演示:
① 作者在这里区分了转换和转型。例如,从
Int32的可空版本到非可空版本(或相反),称为“转换”。但是,涉及不同基元类型的转换,就称为“转型”或“强制类型转换”。 ———— 译注
1 | private static void ConversionsAndCasting() { |
C# 还允许向可空实例应用操作符,例如:
1 | private static void Operators() { |
注意,操作可空实例会生成大量代码。例如以下方法:
1 | private static Int32? NullableCodeSize(Int32? a, Int32? b) { |
编译器生成的 IL 代码等价于以下 C# 代码:
1 | private static Nullable<Int32> NullableCodeSize(Nullable<Int32> a, Nullable<Int32> b) { |
最后要说明的是,可定义自己的值类型来重载上述各种操作符符。使用自己的值类型的可空实例,编译器能正确识别它并调用你重载的操作符(方法)。
19.2 C#的空接合操作符
C# 提供了一个“空接合操作符”(null-coalescing operator),即??操作符,它要获取两个操作数。假如左边的操作数不为 null,就返回这个操作数的值。如果左边的操作数为 null,就返回右边的操作数的值。利用空接合操作符,可以方便地设置变量的默认值。
空接合操作符的一个好处在于,它既能用于引用类型,也能用于可空值类型。
1 | private static void NullCoalescingOperator() { |
?? 在复合情形中更好用。例如,下面这行代码:
String s = SomeMethod1() ?? SomeMethod2() ?? "Untitled";
19.3 CLR 对可空值类型的特殊支持
CLR 内建对可空值类型的支持。这个特殊的支持是针对装箱、拆箱、调用 GetType 和调用接口方法提供的,它使可空类型能无缝地集成到 CLR 中
19.3.1 可空值类型的装箱
1 | // 对 Nullable<T> 进行装箱,要么返回 null,要么返回一个已装箱的 T |
19.3.2 可空值类型的拆箱
1 | // 创建已装箱的 Int32 |
19.3.3 通过可空值类型调用 GetType
在 Nullable<T> 对象上调用 GetType,CLR实际会“撒谎”说类型是 T,而不是 Nullable<T>。以下代码演示了这一行为:
1 | Int32? x = 5; |
19.3.4 通过可空值类型调用接口方法
1 | Int32? n = 5; |





