.NET Framework 2.0 筆記:Nullable Types

摘要:.NET Framework 2.0 筆記:Nullable Types

顧名思義,Nullable 型別就是允許存入 null 值的型別,這當然不是用在參考型別,因為參考型別的變數值本來就可以是 null;它的用途是讓基礎型別(簡單型別)的變數可以有 null 值。例如,資料庫中的整數或布林欄位都可以設定成允許 null,如果某個整數欄位值為 null,那麼取出來存到一般的整數變數時就會有問題。

宣告與初始化

宣告 nullable type 變數的語法有兩種,參考以下範例:

Nullable<int> x = new Nullable<int>(10);
int? x = 10;

如果 nullable type 變數有值,除了可以跟平常一樣直接讀取變數值,也可以利用它的 Value 屬性來取值,例如:

int? x = 10;
Console.WriteLine(x.Value);

但是要注意,如果 nullable type 變數值為 null,上面的程式碼執行時就會出現 exception,因為這樣就變成了要存取一個「沒有東西」的 Value 屬性。

判斷式

判斷某個 nullable type 變數是否為 null 有兩種方法,一個是用 == 或 != 運算子,另一個是用 nullable 型別的 HasValue 屬性,例如:

int? x = null;

if (x != null) ....
if (x.HasValue) ....

注意如果是 nullable 布林型別,當其變數值為 null 時,用在真偽的判斷式中都會傳回 false:

bool? x = null;
if (x) // always false
    Console.WriteLine("false");

另外還有一種簡潔的判斷語法,是用 ?? 運算子,例如:

int? x = null;
int? y = x ?? 5;

第二行的作用等同於

int? y = (x != null) ? x : 5;

與非 nullable type 混用

Nullable type 變數不能直接指定給一般的變數,例如:

int? x = 10;
int y = x;

第二行會無法通過編譯。但是如果用明確轉型:

int y = (int) x;

就可以編譯過。但問題是,如果 x 是 null,儘管可以編譯過,執行時還是會發生 exception,因為 y 是一般的型別,它無法接受 null 值。

另外,任何與 null 值運算的結果,都會是 null,例如:

int? m = null;
int? n = 10;
int? o = m + n;
int? p = m * n;
Console.WriteLine("Nullable 變數運算: m + n = " + o);
Console.WriteLine("Nullable 變數運算: m * n = " + p);

執行結果為:

Nullable 變數運算: m + n = 
Nullable 變數運算: m * n = 

Nullable 與非 nullable 型別可以相互運算:

int? m = 10;
int n = 5;
int? p = m * n;
Console.WriteLine("m * n = " p);

執行結果為:

m * n = 50

但是注意運算的結果也是 nullable type,因此本例的變數 p 必須是 nullable type。

Nullable type 的真正型別

到底 nullable type 編譯之後的實際型別是什麼呢?可以用以下簡單的程式碼測試一下:

tatic int Main( string[] args )
{
   int x = 10;
   int? y = 5;

   Console.WriteLine("type x: {0}", x.GetType().Name);
   Console.WriteLine("type y: {0}", y.GetType().Name);
   Console.WriteLine("type z: {0}", ( x * y ).GetType().Name);

   return 0;
}

輸出:
type x: INT32
type y: INT32
type z: INT32