基元類型為什么需要為null?考慮兩個場景:
1)數據庫中一個int字段可以被設置為null。在C#中,值被取出來后,為了將它賦值給int類型,不得不首先判斷一下它是否為null。如果將null直接賦值給int類型,會引發異常。
2)在一個分布式系統中,服務器需要接收並解析來自於客戶端的數據。一個int型數據可能在傳輸過程中丟失或被篡改了,轉型失敗后應該保存為null值,而不是提供一個初始值。
類似的場景還有很多,所以從.NET 2.0開始,FCL中提供了一個額外的類型:可以為空的類型Nullable<T>。它是一個結構體,聲明如下:
[SerializableAttribute] public struct Nullable<T> where T : struct
因為是結構體,所以只有值引用類型才可以作為“可以為空的類型”(引用類型本身就可以為null)。一個可以為空的int類型表示為:
Nullable<int> i = null;
它也可以表示為:
int? i = null;
語法T?是Nullable<T>的簡寫,兩者可以相互轉換。可以為 null 的類型表示其基礎值類型正常范圍內的值再加上一個null值。例如,Nullable<Int32>,其值的范圍為-2 147 483 648 ~ 2 147 483 647,再加上一個null值。
現在來看看可空類型和基元類型的互相轉換。基元類型提供了其對應的可空類型的隱式轉換,如下所示:
int? i = null; int j = 0; i = j;
反過來,可空類型不可隱式轉換為對應的基元類型,正確的轉換形式如下:
int? i = 123; int j ; if (i.HasValue) { j = i.Value; } else { j = 0; }
但是,這段代碼看上去是不是有點煩瑣?所以,在闡述可空類型的時候,不得不提到??運算符。??最大的用處就是將可空類型的值賦值給對應的基元類型進行簡化,上文代碼的一個簡化形式就是:
int? i = 123; int j = i ?? 0;
int j = i ?? 0;表示的意思是,如果i的HasValue為true,則將i的value賦值給j;否則,就給j賦值為0。