[CLR via C#]可空值类型

一、它为什么而存在

      设计一个数据库时,可将一个列的数据类型定义成一个32位整数,并映射到FCL的Int32数据类型。但是,数据库中的一个列可能允许值为空,也就是说,该列在某一行上允许没有任何值。用.NET Framework处理数据库数据时可能变得相当困难,因为在CLR中,没有办法将一个Int32值表示成null。

二、它到底是什么

为了解决这个问题,Microsoft在CLR中引入了可空值类型的概念。为了理解它们是如何工作的,先来看一下System.Nullable<T>结构,注意它是一个值类型。

 1     [Serializable]
 2     public struct Nullable<T> where T : struct
 3     {
 4         private bool hasValue;
 5 
 6         internal T value;
 7 
 8         public bool HasValue
 9         {
10             get
11             {
12                 return this.hasValue;
13             }
14         }
15         public T Value
16         {
17             get
18             {
19                 if (!this.HasValue)
20                 {
21                     throw new InvalidOperationException("Nullable object must have a value.");
22                 }
23                 return this.value;
24             }
25         }
26 
27         public Nullable(T value)
28         {
29             this.value = value;
30             this.hasValue = true;
31         }
32    
33         public T GetValueOrDefault()
34         {
35             return this.value;
36         }
37         public T GetValueOrDefault(T defaultValue)
38         {
39             if (!this.HasValue)
40             {
41                 return defaultValue;
42             }
43             return this.value;
44         }
45         public override bool Equals(object other)
46         {
47             if (!this.HasValue)
48             {
49                 return other == null;
50             }
51             return other != null && this.value.Equals(other);
52         }
53         public override int GetHashCode()
54         {
55             if (!this.HasValue)
56             {
57                 return 0;
58             }
59             return this.value.GetHashCode();
60         }
61         public override string ToString()
62         {
63             if (!this.HasValue)
64             {
65                 return "";
66             }
67             return this.value.ToString();
68         }
69         public static implicit operator T?(T value)
70         {
71             return new T?(value);
72         }
73         public static explicit operator T(T? value)
74         {
75             return value.Value;
76         }
77     }

1.当使用Nullable<Int32> x = 5时,实际上调用了Nullable的有参构造函数来初始化值类型。

2.当使用Nullable<Int32> x = null时,实际上调用了Nullable的无参构造函数来初始化值类型。

三、C#对可空值类型的支持

C#允许用问号表示法来声明并初始化可空值类型,如Int32? x = 5,相当于Nullable<Int32> x = new Nullable<Int32>(5);

1.C#允许开发人员在可空实例上执行转换和转型

Int32? a = 5;

//通过查看IL可知,实际上是获取了Value属性的值再赋值给b。所以如果a等于Null时,下面一行代码会抛出异常。

Int32 b = (Int32)a;

//通过查看IL可知,实际上是调用了GetValueOrDefault方法获取值,然后再调用new Nullable<Double>构造函数初始化变量。 

Double? c = a;

四、C#的空接合操作符

"??",获取两个操作数,假如左边的操作数不为空,就返回这个操作数的值,否则返回右边操作数的值。

五、CLR对可空值类型的特殊支持

1.可空值类型的装箱

当CLR对一个可空值类型进行装箱时,会检查它是否为空,如果为空,则CLR不进行任何装箱,并返回空值。如果可空实例不为空,CLR从可空实例中取出值,并对其进行装箱。

原文地址:https://www.cnblogs.com/JustYong/p/4756286.html