可為 Null 的值類型 (C# 參考)
可為 Null 的實值型別T?
代表其基礎實值型T
別的所有值,以及額外的Null值。 例如,您可以將下列三個值中的任何一個 bool?
指派給變數: true
、 false
或 null
。 基礎實值型別 T
不能是可為 Null 的實值型別本身。
任何可為 Null 的實值型別都是泛型 System.Nullable<T> 結構的實例。 您可以使用下列任何可交換形式參考具有基礎類型的可為 Null 實值型 T
別: Nullable<T>
或 T?
。
當您需要代表基礎實數值型別的未定義值時,通常會使用可為 Null 的實值型別。 例如,布林值或 bool
、 變數只能是 true
或 false
。 不過,在某些應用程式中,變數值可以是未定義或遺漏的。 例如,資料庫欄位可能包含 true
或 false
,或者它完全不包含任何值,也就是 NULL
。 您可以在該案例中使用 bool?
類型。
宣告與指派
當實值型別隱含轉換成對應的可為 Null 實值型別時,您可以將值指派給可為 Null 實值型別的變數,就像針對其基礎實值型別所做的一樣。 您也可以指派 null
值。 例如:
double? pi = 3.14;
char? letter = 'a';
int m2 = 10;
int? m = m2;
bool? flag = null;
// An array of a nullable value type:
int?[] arr = new int?[10];
可為 Null 之實值型別的預設值代表 null
,也就是其 屬性傳 false
回 的 Nullable<T>.HasValue 實例。
檢查可為 Null 實數值型別的實例
您可以使用is
運算子搭配類型模式來檢查 可為 Null 實數值型別的 null
實例,並擷取基礎類型的值:
int? a = 42;
if (a is int valueOfA)
{
Console.WriteLine($"a is {valueOfA}");
}
else
{
Console.WriteLine("a does not have a value");
}
// Output:
// a is 42
您一律可以使用下列唯讀屬性來檢查和取得可為 Null 實值型別變數的值:
Nullable<T>.HasValue 指出可為 Null 實值型別的實例是否具有其基礎型別的值。
若 HasValue 為
true
,則 Nullable<T>.Value 會取得基礎型別的值。 若 HasValue 為false
,則 Value 屬性會擲回 InvalidOperationException。
下列範例會 HasValue
使用 屬性來測試變數是否包含值,然後再顯示它:
int? b = 10;
if (b.HasValue)
{
Console.WriteLine($"b is {b.Value}");
}
else
{
Console.WriteLine("b does not have a value");
}
// Output:
// b is 10
您也可以比較可為 Null 實數值型別的變數, null
而不是使用 HasValue
屬性,如下列範例所示:
int? c = 7;
if (c != null)
{
Console.WriteLine($"c is {c.Value}");
}
else
{
Console.WriteLine("c does not have a value");
}
// Output:
// c is 7
從可為 Null 的實值型別轉換為基礎型別
如果您想要將可為 Null 實值型別的值指派給不可為 Null 的實值型別變數,您可能需要指定要指派的值來取代 null
。 使用null 聯合運算子 ??
來執行該作業 (您也可以 Nullable<T>.GetValueOrDefault(T) 將 方法用於相同的用途) :
int? a = 28;
int b = a ?? -1;
Console.WriteLine($"b is {b}"); // output: b is 28
int? c = null;
int d = c ?? -1;
Console.WriteLine($"d is {d}"); // output: d is -1
如果您想要使用基礎實值型別的 預設值 來取代 null
,請使用 Nullable<T>.GetValueOrDefault() 方法。
您也可以將可為 Null 的實值型別明確轉換成不可為 Null 的型別,如下列範例所示:
int? n = null;
//int m1 = n; // Doesn't compile
int n2 = (int)n; // Compiles, but throws an exception if n is null
在執行時間,如果可為 Null 的實值型別值為 null
,則明確轉換會 InvalidOperationException 擲回 。
不可為 Null 的實值型 T
別可隱含轉換成對應的可為 Null 實值型別 T?
。
增益運算子
對應的可為 Null 實值型 T
T?
別也支援預先定義的一元和二元運算子或任何多載運算子。 這些運算子也稱為增益運算子,如果一或兩個運算元都是 null
,則會產生 null
;否則,運算子會使用其運算元的內含值來計算結果。 例如:
int? a = 10;
int? b = null;
int? c = 10;
a++; // a is 11
a = a * c; // a is 110
a = a + b; // a is null
注意
bool?
針對類型,預先 &
定義的 和 |
運算子不會遵循本節中所述的規則:即使其中一個運算元為 null
,運算子評估的結果仍可為非 Null。 如需詳細資訊,請參閱布林邏輯運算子一文的可為 Null 的布林邏輯運算子一節。
如果是比較運算子<
>
、 <=
和 >=
,如果其中一個或兩個運算元都是 null
,則結果為 false
,否則會比較運算元的內含值。 請不要因為特定的比較 (例如 <=
) 傳回 false
,就假設相反的比較 (>
) 就會傳回 true
。 下列範例會顯示 10
- 不大於或等於
null
- 也不小於
null
int? a = 10;
Console.WriteLine($"{a} >= null is {a >= null}");
Console.WriteLine($"{a} < null is {a < null}");
Console.WriteLine($"{a} == null is {a == null}");
// Output:
// 10 >= null is False
// 10 < null is False
// 10 == null is False
int? b = null;
int? c = null;
Console.WriteLine($"null >= null is {b >= c}");
Console.WriteLine($"null == null is {b == c}");
// Output:
// null >= null is False
// null == null is True
如果是等號比較運算子==
,如果兩個運算元都是 null
,則結果為 true
,如果其中一個運算元為 null
,則結果為 false
;否則會比較運算元的內含值。
對於不等運算子!=
,如果兩個運算元都是 null
,則結果為 false
,如果只有其中一個運算元為 null
,則結果為 true
,否則會比較運算元的內含值。
如果兩個實值型別之間有 使用者定義的轉換 ,則對應的可為 Null 實值型別之間也可以使用相同的轉換。
Box 處理和 Unbox 處理
可為 Null 實值型 T?
別的實例已 Boxed ,如下所示:
- 若 HasValue 傳回
false
,則會產生 Null 參考。 - 如果 HasValue 傳
true
回 ,則會 Boxed 基礎實數值型別的T
對應值,而不是 的 Nullable<T> 實例。
您可以將實數值型別的 Boxed 值解壓縮到對應的可為 Null 實值型 T
T?
別,如下列範例所示:
int a = 41;
object aBoxed = a;
int? aNullable = (int?)aBoxed;
Console.WriteLine($"Value of aNullable: {aNullable}");
object aNullableBoxed = aNullable;
if (aNullableBoxed is int valueOfA)
{
Console.WriteLine($"aNullableBoxed is boxed int: {valueOfA}");
}
// Output:
// Value of aNullable: 41
// aNullableBoxed is boxed int: 41
如何識別可為 Null 的實值型別
下列範例示範如何判斷實例是否 System.Type 代表建構可為 Null 的實值型別,也就是具有指定型別參數 T
的 System.Nullable<T> 型別:
Console.WriteLine($"int? is {(IsNullable(typeof(int?)) ? "nullable" : "non nullable")} value type");
Console.WriteLine($"int is {(IsNullable(typeof(int)) ? "nullable" : "non-nullable")} value type");
bool IsNullable(Type type) => Nullable.GetUnderlyingType(type) != null;
// Output:
// int? is nullable value type
// int is non-nullable value type
如範例所示,您會使用 typeof 運算子來建立 System.Type 實例。
如果您想要判斷實例是否為可為 Null 的實值型別,請勿使用 Object.GetType 方法來取得 Type 要以上述程式碼測試的實例。 當您在可為 Null 實值型別的實例上呼叫 Object.GetType 方法時,實例會 Boxed 至 Object 。 當可為 Null 實值型別的非 Null 實例 Boxing 相當於基礎型別值的 Boxing 時, GetType 會 Type 傳回代表可為 Null 實值型別之基礎類型的實例:
int? a = 17;
Type typeOfA = a.GetType();
Console.WriteLine(typeOfA.FullName);
// Output:
// System.Int32
此外,請勿使用 is 運算子來判斷實例是否為可為 Null 的實值型別。 如下列範例所示,您無法使用 is
運算子來區分可為 Null 實值型別實例的類型及其基礎類型實例:
int? a = 14;
if (a is int)
{
Console.WriteLine("int? instance is compatible with int");
}
int b = 17;
if (b is int?)
{
Console.WriteLine("int instance is compatible with int?");
}
// Output:
// int? instance is compatible with int
// int instance is compatible with int?
請改用 Nullable.GetUnderlyingType 第一個範例和 typeof 運算子中的 來檢查實例是否為可為 Null 的實值型別。
注意
本節所述的方法不適用於 可為 Null 參考型別的情況。
C# 語言規格
如需詳細資訊,請參閱 C# 語言規格的下列幾節: