首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 2.0 可空型別 完整指南:語法、運算子、比較與空合併運算子

     編輯:關於C語言

什麼是可空型別?

C# 2.0 (ECMA-334) 引入 可空型別,讓實值型別 (int, double, bool, struct 等) 能表示「缺少值」 (null)。語法:在型別後加 ? (如 int?),等同於 Nullable<int>。


int? nullableInt = 1;     // 有值
int? nullableInt2 = null; // 無值 (null)

底層 Nullable<T> 是一個 結構,封裝 T Value 與 bool HasValue 兩個欄位。

核心屬性與隱含轉換

  • HasValue:true 表示有實際值,false 表示 null。
  • Value:取得實際值,若 HasValue == false 擲出 InvalidOperationException。
  • 隱含轉換:非可空型別 → 可空型別 (自動)。可空型別 → 非可空型別需顯式轉換或使用 Value 屬性 (有風險)。

int? a = 10;
int b = 20;
a = b;      // 隱含轉換 int → int?
b = a;      // 編譯錯誤:無法隱含轉換 int? → int
b = a.Value; // 執行期若 a 為 null 會擲出例外

安全取值模式


// 模式 1:HasValue 檢查
if (a.HasValue) b = a.Value;

// 模式 2:GetValueOrDefault() (C# 2.0 內建)
b = a.GetValueOrDefault();      // 若 null 則回傳 0 (int 預設值)
b = a.GetValueOrDefault(-1);    // 自訂預設值

// 模式 3:空合併運算子 ?? (C# 2.0 新增,最推薦)
b = a ?? -1; // a 不為 null 則取 a,否則取 -1

提升運算子:可空型別參與算術/比較

所有預定義一元/二元運算子 (+ - * / % == != > < >= <=) 皆被「提升」為支援可空運算元:

  • 若任一運算元為 null,算術運算結果為 null;比較運算結果為 false (除 == 與 !=)。
  • ==:兩個 null 視為相等 (true);一個 null 一個非 null 為 false。
  • !=:邏輯互補。

int? x = 10;
int? y = null;
int? z = x * y; // z == null
bool eq = (y == null); // true
bool gt = (x > y);     // false (y 為 null)

陷阱:將提升運算結果指派給非可空變數會擲出例外:


int? a = null;
int b = a * 2; // 執行期 InvalidOperationException

空合併運算子 ?? 深度解析

語法:result = nullableExpr ?? fallbackExpr。若 nullableExpr 非 null 則取其值,否則取 fallbackExpr。fallbackExpr 型別需能隱含轉換為 result 型別。


int? a = 100;
int? b = null;
int c = a ?? -1; // 100
int d = b ?? -1; // -1

// 串連用法:多層備援
string config = userSetting ?? systemDefault ?? "HardCodedDefault";

適用場景與最佳實踐

  1. 資料庫欄位映射:DbDataReader.GetInt32 遇 DBNull 擲出例外,改用 int? 配合 ?? 优雅處理。
  2. 選用性參數:避免多載爆炸,用 void Foo(int? timeout = null) 並在內部 timeout ??= DefaultTimeout (C# 8.0 ??=)。
  3. 領域模型:DateTime? BirthDate 明確表達「未知」而非 DateTime.MinValue。

結語

可空型別填補了實值型別無法表達「無值」的語意缺口,配合提升運算子與 ??,讓含有選用性資料的邏輯更清晰、安全。記住:優先用 HasValue/?? 避免直接存取 Value 擲出例外。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved