看似簡單的三元運算子 a ? b : c,隱藏著 C# 編譯器嚴格的「型別統一」規則。一段代碼 object o = i > 3 ? null : 3.5; 直接導致編譯失敗,原因何在?
int i = 1;
object o = i > 3 ? null : 3.5; // CS0173: 無法判斷 '' 和 'double' 之間的類型
直覺認為 object 可接受任何型別,為何編譯器拒絕?
正確代碼 o = i + j > 3 ? 3 : 3.5; 的 IL:
L_000b: ldloc.1 // i
L_000c: ldloc.2 // j
L_000d: add
L_000e: ldc.i4.3
L_000f: bgt.s L_001c // >3 跳轉
L_0011: ldc.r8 3.5 // false 分支:壓入 double 3.5
L_001a: br.s L_0025
L_001c: ldc.r8 3 // true 分支:壓入 double 3 (隱式轉換)
L_0025: box [mscorlib]System.Double // 統一裝箱為 double
L_002a: stloc.0 // 存入 object o
關鍵規則:編譯器會在編譯期推導 b 與 c 的最佳通用型別,雙方必須存在隱式轉換關係。null 無隱式轉換至 double,故報錯。
double? n = 3.5; o = i > 3 ? null : n;(推薦,語意清晰)o = i > 3 ? (double?)null : 3.5; 或 o = i > 3 ? (object)null : (object)3.5;double? o;
double? n = 3.5;
o = i > 3 ? null : n; // IL 直接操作 Nullable,無 box 指令
IL 顯示 initobj Nullable`1<double> 初始化空值,完全避免堆積配置與裝箱開銷。
遇到「語法合理但編譯失敗」或「行為違背直覺」時,請出 IL(ildasm / dotnet-ildasm / Visual Studio「反組譯」視窗)。IL 是編譯器意圖的真實投影,能瞬間穿透語法糖霧霾,直達型別系統核心邏輯。