首先我們都知道引用類型默認值都是null,而值類型的默認值都有非null。

為什麼引用類型可以為空?因為引用類型變量都是保存一個對象的地址引用(就像一個url對應一個頁面),而引用類型值為null的時候是變量值指向了一個空引用(如同一個空的url)

那為什麼值不能有空值呢?其實很簡單,因為如int值范圍是-2147483648到2147483647。其中根本就沒有給null值留那麼一個位置。

舉個栗子吧,我們定義一個人(Person),它有三個屬性出生日期(BeginTime)、死亡日期(EndTime)、年齡(Age)。
如果這個人還健在人世,請問怎麼給死亡日期賦值?有人很聰明說“為空啊”。是的,這就是我們的需求。
微軟在C#2.0的時候就為我們引入了可null值類型( System.Nullable<T> ),那麼下面來定義Person類。
1 public class Person
2 {
3 /// <summary>
4 /// 出生日期
5 /// </summary>
6 public DateTime BeginTime { get; set; }
7 /// <summary>
8 /// 死亡日期
9 /// </summary>
10 public System.Nullable<DateTime> EndTiem { get; set; }
11 public int Age
12 {
13 get
14 {
15 if (EndTiem.HasValue)//如果掛了(如果有值,證明死了)
16 {
17 return (EndTiem.Value - BeginTime).Days;
18 }
19 else//還沒掛
20 {
21 return (DateTime.Now - BeginTime).Days;
22 }
23 }
24 }
25 }
這樣,我們就可以很容易獲得一個人的年齡了。
static void Main(string[] args)
{
Person p1 = new Person()
{
BeginTime = DateTime.Parse("1990-07-19")
};
Person p2 = new Person()
{
BeginTime = DateTime.Parse("1893-12-26"),
EndTiem = DateTime.Parse("1976-09-09")
};
Console.WriteLine("我今年" + p1.Age + "歲。");
Console.WriteLine("毛爺爺活了" + p2.Age + "歲。");
Console.ReadKey();
}
我們前面用到了 System.Nullable<DateTime> 來表示可空時間類型,其實平時我們用得更多的是 DateTime? 直接在類型T後面加一個問號,這兩種是等效的。多虧了微軟的語法糖。
我們來看看 System.Nullable<T> 到底是何物。

搜噶,原來是一個結構。還看到了我們屬性的 HasValue和Value屬性。原來竟這般簡單。一個結構兩個屬性,一個存值,一個存是否有值。那麼下面我們也來試試吧。

不好意思,讓大家失望了。前面我們就說過了,值類型是不可以賦值null的(結構也是值類型)。
怎麼辦!怎麼辦!不對啊,微軟自己也是定義的結構,它怎麼可以直接賦值null呢。(奇怪,奇怪,畢竟是人家微軟自己搞得,可能得到了特殊的待遇吧)
可是,這樣就讓我們止步了嗎?NO!我們都知道,看微軟的IL(中間語言)的時候,就像脫了它的衣服一樣,很多時候不明白的地方都可以看個究竟,下面我們就去脫衣服。
首先,我們用幾種不同的方式給可空類型賦值。
static void Main(string[] args)
{
System.Nullable<int> number1 = null;
System.Nullable<int> number2 = new System.Nullable<int>();
System.Nullable<int> number3 = 23;
System.Nullable<int> number4 = new System.Nullable<int>(88);
Console.ReadKey();
}
然後用reflector看編譯後的IL。

原來如此,可空類型的賦值直接等效於構造實例。賦null時其實就是調用空構造函數,有值時就就把值傳入帶參數的構造函數。(柳暗花明又一村。如此,我們是否可以接著上面截圖中的 MyNullable<T> 繼續模擬可空類型呢?且繼續往下看。)
public struct MyNullable<T> where T : struct
{
//錯誤 1 結構不能包含顯式的無參數構造函數
//還好 bool默認值就是false,所以這裡不顯示為 this._hasValue = false也不會有影響
//public MyNullable()
//{
// this._hasValue = false;
//}
public MyNullable(T value)//有參構造函數
{
this._hasValue = true;
this._value = value;
}
private bool _hasValue;
public bool HasValue//是否不為空
{
get { return _hasValue; }
}
private T _value;
public T Value//值
{
get
{
if (!this._hasValue)//如沒有值,還訪問就拋出異常
{
throw new Exception(" 可為空的對象必須具有一個值");
}
return _value;
}
}
}
喲西,基本上已經模擬出了可空類型出來的。(但是我們還是不能直接賦值,只能通過構造函數的方式來使用自定義的可空類型)。
全部代碼如下:

和系統的可空類型得出了相同的結果。


有同學問,怎麼樣才可以做到直接賦值呢?這個我也沒有什麼好的辦法,或許需要編譯器的支持。
以上內容都是胡說八道。希望能對您有那麼一點點用處,感謝閱讀。
(首發鏈接:http://www.cnblogs.com/zhaopei/p/5537759.html )