—— 數據精度保衛戰中的checked與unchecked秘籍
📌 核心概念速覽
1. 隱式轉換
- 自動發生,無數據丟失風險(如
int
→long
) - 遵循"小類型→大類型"路徑(見下圖??)
[圖1:C#隱式數字轉換路徑 | 箭頭方向為安全轉換路徑]
2. 顯式轉換
- 需強制類型聲明(如
(int)3.14
) - 可能導致數據截斷或溢出(如
long
→int
)
? 溢出檢測:程序安全的守門人
默認情況下,C#處于 unchecked
上下文(不檢測溢出)。需主動啟用安全檢測:
操作方式 | 語法示例 | 作用 |
---|---|---|
運算符 | checked(expr) | 單表達式溢出時拋OverflowException |
語句塊 | checked { ... } | 整段代碼啟用溢出檢測 |
禁用檢測 | unchecked(expr) | 強制忽略溢出(結果可能異常) |
// 經典案例對比
ushort sh = 2000;
byte sb;// 不檢測:丟失高位字節 → 輸出208
sb = unchecked((byte)sh); // 檢測:溢出時崩潰 → 拋出OverflowException
sb = checked((byte)sh);
💡 嵌套技巧
checked
與unchecked
可多層嵌套,精準控制風險范圍:
checked {unchecked { /* 此處允許溢出 */ } checked { /* 此處嚴格檢測 */ }
}
🔁 顯式轉換的六大雷區與應對策略
1. 整數 → 整數
- ?
unchecked
:直接截斷高位(如0x1234
→0x34
) - ?
checked
:溢出必拋異常
2. 浮點 → 整數
- 小數部分無條件截斷(3.99 → 3)
- ?? 超范圍時:
```mermaidgraph LRA[值超出目標范圍] --> B{checked?}B -->|Yes| C[拋OverflowException]B -->|No| D[結果未定義!]```
3. decimal → 整數
- 任何超范圍轉換 → 必拋
OverflowException
(無unchecked
豁免權!)
4. double → float
- 值過小 → 歸零
- 值過大 → ±∞(正/負無窮大)
5. 浮點 → decimal
- 值過小 → 歸零
- 值過大 → 立即拋異常
6. decimal → 浮點
- 永遠成功,但可能損失精度(decimal精度高于float/double)
[圖2:顯式數字轉換規則矩陣 | 展示各類型轉換風險點]
[圖3:浮點轉整數流程示意圖 | 突出截斷與溢出邏輯]
💎 最佳實踐總結
1. 默認策略
- 生產環境建議全局啟用
checked
,在Program.cs
中添加:Checked.Enable(); // .NET 6+全局啟用檢測
2. 性能敏感場景
- 在確定性無溢出區塊使用
unchecked
提升性能(如加密計算)
3. 浮點轉換黃金法則
// 先檢查范圍再轉換
double d = 1e20;
if (d >= float.MinValue && d <= float.MaxValue)
{float safeFloat = (float)d;
}