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<int> nullable1 = new Nullable<int>(3);
Nullable<int> nullable2 = 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类型的代价是很高的,如非必须,不要使用。
.entrypoint
// Code Size: 63 byte(s)
 .maxstack 3
.locals init (
[mscorlib]System.Nullable`1<int32> nullable1,
int32 num1,
[mscorlib]System.Nullable`1<int32> nullable2,
int32 num2,
[mscorlib]System.Nullable`1<int32> nullable3)
L_0000: nop
L_0001: ldloca.s nullable1
L_0003: ldc.i4.3
L_0004: call instance void [mscorlib]System.Nullable`1<int32>::.ctor(!0)
L_0009: nop
L_000a: ldc.i4.1
L_000b: stloc.1
L_000c: ldloc.0
L_000d: stloc.2
L_000e: ldloc.1
L_000f: stloc.3
L_0010: ldloca.s nullable2
L_0012: call instance bool [mscorlib]System.Nullable`1<int32>::get_HasValue()
L_0017: brtrue.s L_0025
L_0019: ldloca.s nullable3
L_001b: initobj [mscorlib]System.Nullable`1<int32>
L_0021: ldloc.s nullable3
L_0023: br.s L_0033
L_0025: ldloca.s nullable2
L_0027: call instance !0 [mscorlib]System.Nullable`1<int32>::GetValueOrDefault()
L_002c: ldloc.3
L_002d: add
L_002e: newobj instance void [mscorlib]System.Nullable`1<int32>::.ctor(!0)
L_0033: box [mscorlib]System.Nullable`1<int32>
L_0038: call void [mscorlib]System.Console::WriteLine(object)
L_003d: nop
L_003e: ret

最后提一下 ?? 这个操作符。

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.
posted on 2008-12-29 15:38  胡成忠  阅读(2415)  评论(0编辑  收藏  举报