1. 簡寫
- 以後綴
?之前接在類型名稱後面,也就是T?可以視同為Nullable<T> - 舉例來說,下列四個變數類型名稱完全等價:
Nullable<int>Nullable<int32>int?int32
2. 定義
- Nullable 的核心程式碼為:
public struct Nullable<T> where struct // 類型約束為非空值類型
{
private readonly T value;
private readonly bool hasValue;
public Nullable(T value)
{
this.value = value;
this.hasValue = true;
}
public bool HasValue { get { return hasValue; } }
public T Value
{
get
{
if (!hasValue)
{
threw new InvalidOperationException();
}
return value;
}
}
}
- 由於 Nullable 的空值定義為
hasValue == false, 故以下兩者為等價int? x = new int?();int? x = null;
3. 轉換
- 允許 T 到 Nullable
的隱式轉換
int x = 5;
int? y = x;
- 允許 Nullable
到 T 的顯式轉換
int? x = 5;
int y = (int)x;
-
通過填充 null 值擴展已有功能的過程稱為 提升 lifting。
-
C# 允許對非可空類型
T做運算子重載,但Nullable<T>同時也會重載相同的運算子,稱為 提升運算子 lifting operator。- 可重載的運算子包含:
- 一元運算子:
+,++,-,--,!,~,true,false - 二元運算子:
+,-,*,/,%,&,|,^,>>,<< - 等價運算子:
==,!= - 關係運算子:
<,>,<=,>=
- 一元運算子:
- 提升運算子的規則:
true和false運算子不能被提升。T必須是非可空值,其運算子才能被提升。- 對於等價運算子和關係運算子,原運算子的返回類型必須是
bool類型 - 對於
Nullable<bool>的&與|運算子有單獨定義
- 提升運算子範例:
int? nullInt = null; int? five = 5; int? four = 4; Console.WriteLine(-nullInt); // null Console.WriteLine(-five); // -5 Console.WriteLine(five + nullInt); // null Console.WriteLine(five + four); // 4 Console.WriteLine(four & nullInt); // null Console.WriteLine(four & five); // 4 Console.WriteLine(nullInt == nullInt); // true Console.WriteLine(five == five); // true Console.WriteLine(five == nullInt); // false Console.WriteLine(five == four); // false Console.WriteLine(four < five); // true Console.WriteLine(nullInt < five); // false Console.WriteLine(four < nullInt); // false Console.WriteLine(nullInt < nullInt); // false Console.WriteLine(nullInt <= nullInt); // false- 可空值邏輯真值表: |x|y|x&y|x|y|x^y|!x| |---|---|---|---|---|---| |true|true|true|true|false|false| |true|false|false|true|true|false| |true|null|null|true|null|false| |false|true|false|true|true|true| |false|false|false|false|false|true| |false|null|false|null|null|true| |null|true|null|true|null|null| |null|false|false|null|null|null| |null|null|null|null|null|null|
- 可重載的運算子包含:
-
注意 C# 2中,比較操作的結果不能為 null
-
在 SQL 中,比較中的兩者中若有一者為 null 則結果不能預期
4. as 運算子
- 在 C# 2,
as除了可用於物件,也可用於可空值類型。 - 當原始引用的類型不匹配,或為 null 時,返回 null 值:
public static void Main()
{
object[] obj = new object[]{
null,
"3",
'3',
3,
5.5
};
foreach (var o in obj) print(o);
}
public static void print(object o)
{
int? num = o as int?;
Console.WriteLine(num.HasValue ? num : "something");
}
// something
// something
// something
// 3
// something
5. ?? 運算子
- 當
??前非 null 時依原本的值代入,若為null則以??後的值代入。
int a = 5;
int? b = 10;
int? c = null;
Console.WriteLine("a + b = {0}", a + (b ?? 0)); // 15
Console.WriteLine("a + b = {0}", a + (c ?? 0)); // 5
6. ?. 運算子
- 當
?.前為非 null 時,繼續往下做,可連續
List<int> a = null;
List<int> b = default;
List<int> c = new List<int>{ 1,3,5,7,9 };
Console.WriteLine(a?.Count); //
Console.WriteLine(b?.Count); //
Console.WriteLine(c?.Count); // 5