程式中,Null是一個很常用來判別的一個型別,Null代表的是一個空的型別,跟Undefined有很相似之處,一般初學者很常會在程式判斷上,會搞不清楚什麼時候該用Null,什麼時候要用Undefined去判別。不過在程式設計上,筆者會建議在變數的宣告時,盡可能給予一個基本值,因為在Null和Undefined的判斷上,大部分都會是判斷發生的例外,這樣會比較減少用過多的if去吃掉運算效能,不過在C#裡,Null是一個很特別的型別,微軟為它創造了一個許多屬於它處理的獨立個體。以下是微軟為Null下的定義:
可為 Null 的型別有下列特性:
- 可為 Null 的型別代表能夠指派 null 值的實值型別變數。您無法根據參考型別建立可為 Null 的型別 (參考型別已支援 null 值)
- 語法 T? 是 Nullable<T> 的簡略表示法,其中 T 是實值型別。兩種格式可以互相變更
- 就像針對一般實值型別一樣,將值指派至可為 Null 的型別,例如 int? x = 10; 或 double? d = 4.108;
-
- 如果變數包含值 HasValue 屬性會傳回 true,而如果變數是 null 則傳回 false
- 如果有指派值,Value 屬性便會傳回值。否則,會擲回 System.InvalidOperationException。
- 可為 Null 的型別變數預設值會將 HasValue 設定為 false。Value 則未定義
- 當目前值為 null 的可為 Null 型別指派至不可為 Null 的型別時,請使用 ?? 運算子指派將套用的預設值,例如 int? x = null; int y = x ?? -1;
- 不允許巢狀式可為 Null 的型別。不會編譯下列程式碼行:Nullable<Nullable<int>> n;
可為 Null 的型別可以代表基礎型別的所有值,也可以代表另一個 null 值。您可以使用下列其中一種方法宣告可為 Null 的型別:
System.Nullable<T> variable
-或-
T? variable
T 是可為 Null 之型別的基礎型別,T 可以是任何實值型別 (包括 struct,但不能是參考型別)。
何時該使用可為 null 的型別,可舉一般的布林變數為例,這種變數有兩個可能的值:true 和 false。但沒有值可以代表「未定義」。在許多設計程式的應用程式中,特別是資料庫互動的程式,變數有可能是以未定義的狀態存在。例如,資料庫中的某個欄位可能包含 true 或 false 值,但也可能不包含任何值。同樣地,參考型別可以設定為 null 表示其並非初始化的。
由於這些值的性質不同,就需要在程式上另做設計,包括使用其他變數存放狀態資訊、使用特殊值等等。可為 null 的型別修飾詞能夠讓 C# 建立表示未定義之值的實值型別 (Value Type) 變數。
可為 Null 的型別範例
可為 Null 的型別成員
可為 null 之型別的每個執行個體 (Instance) 有兩個公用唯讀屬性:
- HasValueHasValue 屬於 bool 型別。當變數包含非 null 的值時,該屬性會設定為 true。
- ValueValue 的型別與基礎型別相同。如果 HasValue 為 true,Value 會包含有意義的值。如果 HasValue 為 false,存取 Value 將會擲回 InvalidOperationException。
在這個範例中,會先使用 HasValue 成員測試變數是否包含值,然後才會嘗試顯示該值。
int? x = 10; if (x.HasValue) { System.Console.WriteLine(x.Value); } else { System.Console.WriteLine("Undefined"); }
也可使用下列範例完成測試值的作業:
int? y = 10; if (y != null) { System.Console.WriteLine(y.Value); } else { System.Console.WriteLine("Undefined"); }
明確轉換
您可以明確使用轉型或使用 Value 屬性,將可為 null 的型別轉換成標準型別。例如:
int? n = null; //int m1 = n; // Will not compile. int m2 = (int)n; // Compiles, but will create an exception if x is null. int m3 = n.Value; // Compiles, but will create an exception if x is null.
如果在兩資料型別之間定義了使用者定義轉換,這兩個資料型別的可為 Null 的型別版本也可以使用該轉換。
隱含轉換
可為 Null 的型別 (Nullable Type) 可使用 null 關鍵字設為 null,如下列範例所示:
int? n1 = null;
從一般型別轉換成可為 null 的型別是隱含轉換。
int? n2; n2 = 10;
可為 Null 的型別也可以使用預先定義的一元和二元運算子,以及現有實值型別的任何使用者定義運算子。如果運算元都是 null,這些運算子就會產生 null 值,否則運算子會使用所包含的值計算結果。例如:
int? a = 10; int? b = null; a++; a = a * 10; a = a + b;
使用可為 Null 的型別執行比較時,如果其中一個可為 Null 的型別是 null,比較的評估結果一定會是 false。因此,請千萬不要認為比較結果為 false 時,反之就是 true。例如:
int? num1 = 10; int? num2 = null; if (num1 >= num2) { System.Console.WriteLine("num1 is greater than or equal to num1"); } else { }
因為 num2 是 null,導致其中並未包含值,所以上述 else 陳述式中的結果是無效的。
兩個皆為 null 之可為 Null 的型別,其比較的評估結果將會是 true。
可為 null 的 bool? 型別可包含三種不同的值:true、false 和 null。如需從 bool? 轉換為 bool 的詳細資訊,請參閱 HOW TO:從 bool? 安全轉型至 bool (C# 程式設計手冊)。
可為 Null 的布林值就像 SQL 中使用的布林值變數型別。為確保 & 和 | 運算子產生的結果與 SQL 的三值布林型別一致,提供下列預先定義的運算子:
bool? operator &(bool? x, bool? y)
bool? operator |(bool? x, bool? y)
bool? operator |(bool? x, bool? y)
這些運算子的結果列於下表:
X
|
y
|
x&y
|
x|y
|
---|---|---|---|
true
|
true
|
true
|
true
|
true
|
false
|
false
|
true
|
true
|
null
|
null
|
true
|
false
|
true
|
false
|
true
|
false
|
false
|
false
|
false
|
false
|
null
|
false
|
null
|
null
|
true
|
null
|
true
|
null
|
false
|
false
|
null
|
null
|
null
|
null
|
null
|
只有當以可為 Null 的型別 (Nullable Type) 為基礎的物件不是 Null 時,該物件才會是 boxed。如果 HasValue 為 false,則會將物件參考指派為 null,而不會做 boxing 處理。例如:
bool? b = null; object o = b;
如果物件為非 null (若 HasValue 是 true),便會進行 boxing 處理,但只有可為 Null 的物件所依據的基礎型別會是 boxed。對不可為 Null 的數值型別執行 box 處理就會 box 數值型別本身,而非包裝實值型別的 System.Nullable<T>。例如:
bool? b = false; int? i = 44; object bBoxed = b; object iBoxed = i;
這兩個 boxed 物件與透過對不可為 Null 型別執行 box 處理而建立的物件相同。而且就像不可為 null 的 boxed 型別一樣,可以 unboxed 成可為 null 的型別,如下列範例所示:
bool? b2 = (bool?)bBoxed; int? i2 = (int?)iBoxed;
在執行 box 的動作時,可為 Null 型別的行為提供了兩個優點:
- 可以測試可為 Null 的物件及其 boxed 對應物件是否為 null:
bool? b = null; object boxedB = b; if (b == null){//結果為True} if (boxedB == null){//結果為True}
- Boxed 可為 Null 型別完全支援基礎型別的功能:
double? d = 44.4;
object iBoxed = d;
// Access IConvertible interface implemented by double.
IConvertible ic = (IConvertible)iBoxed;
int i = ic.ToInt32(null);
string str = ic.ToString();
-雲遊山水為知已逍遙一生而忘齡- 電腦神手
沒有留言:
張貼留言