本文资料引用自李建忠先生的演讲稿
C# 引入Nullable类型,允许我们将值类型赋值为null。
其实质上是在Framework中增加了一个Nullable<T>的泛型结构类型。
[SerializableAttribute()]
public struct Nullable<T> : IFormattable, IComparable, INullableValue
where T : ValueType
看看上面的声明,我们可以确定,Nullable是一个值类型,而且限制类型参数为值类型。
另外C#在语法层面作了简化,见下面的代码。
int? x = 3;
Nullable<int> y = new Nullable<int>(3);
看看反编译的结果。
实际上,编译器会将缩写方式处理成完整的结构体创建代码。
Nullable包含两个有用的属性,HasValue用来判断类型是否为空,如果不为空则可以通过Value属性获取其基础类型的值。
当其值不为空时,可以直接使用其基础类型的运算符进行操作。GetValueOrDefault 方法可以获取值或者基础类型的缺省值。
int? x = 3;
int y = 1;
Console.WriteLine(x + y);
不过看看这段代码的反编译结果,你可能会发现一些问题。
Nullable<int> nullable1 = new Nullable<int>(3);
int num1 = 1;
Nullable<int> nullable2 = nullable1;
int num2 = num1;
Console.WriteLine(nullable2.get_HasValue() ? new Nullable<int>(nullable2.GetValueOrDefault() + num2) : new Nullable<int>());
原本简单的代码变得很复杂,编译器创建了新的Nullable对象,而且通过判断,如发现Nullable对象为空,则放弃加法操作,直接返回空。
继续看反编译的IL代码,还出现了box指令,因此Nullable类型的代价是很高的,如非必须,不要使用。
最后提一下 ?? 这个操作符。
The ?? defines a default value that is returned when a nullable type is assigned to a non-nullable type.
// ?? operator example.
int? x = null;
int y = x ?? -1; // Assigns y to -1 if x is null.
相当于
int y = x.HasValue ? x.GetValueOrDefault() : -1;