可空值类型首先表示一个值类型,然后表示该值类型可以为空。值类型原本是不能为空的,为了表达一个值类型为空,引入了System.Nullable<T>类型,该类型本身也是一个值类型。
在C#中,Int32?等价于Nullable<Int32>. ??等价于?:。
private static void NullCoalescingOperator() { Int32? b = null; // x = (b.HasValue) ? b.Value : 123 Int32 x = b ?? 123; Console.WriteLine(x); // "123" // String temp = GetFilename(); // filename = (temp != null) ? temp : "Untitled"; String filename = GetFilename() ?? "Untitled"; }
当CLR对一个Nullable<T>实例进行装箱时,会检查它是否为null。如果是,直接返回null值;如果不为null,CLR从可空实例中取出值,并对其进行装箱。
private static void Boxing() { // Boxing Nullable<T> is null or boxed T Int32? n = null; Object o = n; // o is null n = 5; o = n; // o refers to a boxed Int32 Console.WriteLine("o's type={0}", o.GetType()); // "System.Int32" }
对于已装箱值类型的引用是null,而且要把它拆箱为一个Nullable<T>,那么CLR会将Nullable<T>的值设置为null.
private static void Unboxing() { // Create a boxed Int32 Object o = 5; // Unbox it into a Nullable<Int32> and into an Int32 Int32? a = (Int32?)o; // a = 5 Int32 b = (Int32)o; // b = 5 // Create a reference initialized to null o = null; // Unbox?it into a Nullable<Int32> and into an Int32 a = (Int32?)o; // a = null b = (Int32) o; // NullReferenceException }
在Nullable<T>对象上调用GetType时,CLR会返回T而不是Nullable<T>.
Nullable<T>没有实现IComparable<T>, C#编译器允许代码通过编译。
private static void InterfaceMethods() { Int32? n = 5; Int32 result = ((IComparable<Int32>)n).CompareTo(5); // Compiles & runs OK }