可空值類型:C# 基本面

小提示

本文屬於 基礎 部分,適合至少會一種程式語言並正在學習 C# 的開發者。 如果你是程式新手,建議先從 入門 教學開始。 更多細節請參閱語言參考中的 Nullable value types

可空值類型T?代表其底層值類型T的所有值,加上一個額外null值。 型態 int? 的變數可表示任意整數或 null ,表示「無值」。

預設情況下,像 intboolDateTime 這樣的值類型無法持有 null。 這種行為效率高,能避免許多錯誤。 然而,當某個數值可能真的缺失時,這種限制就會造成問題。 一個常見的情況是從資料庫讀取:整數欄位可能包含一個數字,也可能完全沒有值(NULL 在 SQL 中)。 簡單的 int 無法代表那種不存在,但 int? 可以。

宣告一個可空的值型別

附加 ? 到任意值類型以使其可為空:

int?    age      = null;    // integer with no value yet
double? price    = 9.99;    // nullable double with a value
bool?   isActive = null;    // boolean with no value

age = 30;                   // assign a value later

int?[] scores = [100, null, 85, null, 72]; // array with absent entries

可空值型別的預設值為 null,而非底層型別的預設值。

檢查是否有某個數值存在

檢查可空值型別並提取其值的推薦方法是使用型別模式

int? temperature = 72;

if (temperature is int degrees)
{
    Console.WriteLine($"Temperature is {degrees}°F.");
}
else
{
    Console.WriteLine("Temperature is not recorded.");
}
// Output: Temperature is 72°F.

is int degrees該模式僅在temperature非空時匹配,且同時將值綁定於 degrees。 你可以在同一步驟中同時完成空驗證和取值。

或者,可以使用 HasValueValue 屬性:

int? count = 42;

if (count.HasValue)
{
    Console.WriteLine($"Count is {count.Value}.");
}
else
{
    Console.WriteLine("Count has no value.");
}
// Output: Count is 42.

偏好新程式碼的 is T value 模式。 它引入了一個新的不可為空的變數,此變數的作用域限定於匹配的分支中,使意圖更明確,並消除在 null 檢查之外錯誤使用 Value 的誘惑,以避免拋出 InvalidOperationException

你也可以直接與 null 比較:

int? quantity = null;

if (quantity != null)
{
    Console.WriteLine($"Quantity: {quantity.Value}");
}
else
{
    Console.WriteLine("Quantity is not set.");
}
// Output: Quantity is not set.

取得一個有備用價值的數值

當你需要從可空值中取得非可空值時,可以使用 GetValueOrDefault 或空合併 ?? 運算子。

int? rating = null;

int result1 = rating.GetValueOrDefault();    // 0 (default for int)
int result2 = rating.GetValueOrDefault(-1);  // -1 (specified fallback)

Console.WriteLine(result1); // 0
Console.WriteLine(result2); // -1

rating = 5;
int result3 = rating.GetValueOrDefault(-1);  // 5 (actual value)
Console.WriteLine(result3); // 5

??運算符號通常內嵌時更簡潔:

int? priority = null;

int effective = priority ?? 0;  // 0 because priority is null
Console.WriteLine(effective);   // 0

priority  = 3;
effective = priority ?? 0;      // 3 because priority has a value
Console.WriteLine(effective);   // 3

兩種方法在存在實際值時回傳該值,不存在時則回傳你指定的備援值。

具有可空值型態的算術

對可空值類型的算術和比較運算子會被提升:當任一運算元為null時,結果為null而非錯誤。

int? a = 10;
int? b = 20;
int? c = null;

int? sum     = a + b;   // both non-null: result is 30
int? product = a * c;   // one operand is null: result is null

Console.WriteLine(sum);               // 30
Console.WriteLine(product.HasValue);  // False — null propagates through arithmetic

空值會在預設情況下通過算術運算傳播。 為了防止空結果進一步擴散,請在計算前使用??GetValueOrDefault提取該值。

參見