繼上一篇「你確認C#中TryParse比Parse好?動手測試才知道!」後,本文繼續講《編寫高質量代碼改善C#程序的157個建議》一書第5個建議「使用int?來確保值類型也可以為null」。喜歡本書請到各大商城購買原書,支持正版。
基元類型為什麼需要為null?考慮兩個場景:
資料庫中一個int欄位可以被設置為null。在C#中,值被取出來後,為了將它賦值給int類型,不得不首先判斷一下它是否為null。如果將null直接賦值給int 類型,會引發異常。
在一個分布式系統中,伺服器需要接收並解析來自於客戶端的數據。一個int型數據可能在傳輸過程中丟失或被篡改了,轉型失敗後應該保存為null值,而不是提供一個初始值。
類似的場景還有很多,所以從.NET 2.0開始,FCL中提供了一個額外的類型:可以為空的類型Nullable。它是一個結構體,聲明如下:
[SerializableAttribute]
public struct Nullable<T> where T : struct因為是結構體,所以只有值引用類型才可以作為「可以為空的類型」(引用類型本身就可以為null)。一個可以為空的int類型表示為:
Nullableeint> i = null;它也可以表示為:
int? i = null;語法T?是 Nullable的簡寫,兩者可以相互轉換。可以為 null 的類型表示其基礎值類型正常範圍內的值再加上一個null值。例如,Nullable,其值的範圍為—2147 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。
下一篇我們接著讀《建議6:區別readonly和const的使用方法》,歡迎關注微信公眾號【小市民在西河】。