| 類型 | 預設 (無關鍵字) | checked 內文 | unchecked 內文 |
| 常數運算式 (編譯期可計算) | 編譯錯誤 (CS0220) | 編譯錯誤 | 允許,結果截斷 |
| 非常數運算式 (執行期計算) | 依專案設定 (預設 unchecked:截斷) | 執行期拋出 OverflowException | 截斷,不拋出 |
const int MAX = int.MaxValue;
// 常數運算式
int c1 = MAX + 1; // CS0220 編譯錯誤
int c2 = checked(MAX + 1); // CS0220 編譯錯誤
int c3 = unchecked(MAX + 1); // 通過,c3 = -2147483648
// 非常數運算式
int v = GetRuntimeValue();
int r1 = v + 1; // 預設截斷
int r2 = checked(v + 1); // 可能拋出 OverflowException
int r3 = unchecked(v + 1); // 截斷
方法邊界限制:checked 不跨越方法呼叫
int Multiply(int x, int y) => x * y; // 方法內無 checked
// 呼叫端加 checked 無效!
int result = checked(Multiply(1000000, 1000000)); // 不拋出,Multiply 內部 unchecked
// 正確做法 1:方法內部加 checked
int MultiplySafe(int x, int y) { checked { return x * y; } }
// 正確做法 2:回傳前檢查
int MultiplyCheck(int x, int y) {
if (x != 0 && y > int.MaxValue / x) throw new OverflowException();
return x * y;
}
專案層級預設控制
- Visual Studio:專案屬性 → Build → "Check for arithmetic overflow/underflow" (
/checked+)
.csproj:<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
- 預設
unchecked (效能優先)
階乘範例:逐步檢測
long Factorial(int n)
{
long result = 1;
for (int i = 2; i <= n; i++)
{
checked { result *= i; } // 每步檢測
}
return result;
}
// 測試
try { Console.WriteLine(Factorial(25)); } // 25! > long.MaxValue
catch (OverflowException) { Console.WriteLine("溢位發生於 25!"); }
最佳實踐決策表
| 場景 | 建議 | 理由 |
| 金融計算、索引運算、緩衝區大小 | 區塊 checked | 正確性優先,溢位即 Bug |
| 雜湊、加密、隨機數、位元操作 | unchecked 明確標記 | 語意明確:預期回繞行為 |
| 高效能熱路徑 | 手動檢查 if (a > MAX - b) | 避免例外開銷,分支預測友善 |
| 庫開發 | 文件化行為,不強制專案設定 | 讓消費者自行決定 |
| 常數運算式 | 依賴編譯期檢測 | 零成本捕捉 Bug |
decimal 內建溢位檢查
decimal d = decimal.MaxValue;
d = d + 1; // 無需 checked,直接拋出 OverflowException
decimal 專為金融設計,永遠檢查溢位,無法關閉。
總結
checked/unchecked 提供靈活的整數溢位控制:運算式/區塊兩種形式、常數/非常數不同語意、不跨越方法邊界。關鍵決策:金融/關鍵計算用 checked、位元/雜湊用 unchecked、效能熱路徑手動檢查。decimal 內建檢查無需額外關鍵字。
- 上一篇文章: C# 特殊運算子總覽:三元條件、遞增遞減、new、typeof、checked/unchecked
- 下一篇文章: C# typeof 運算符詳解:獲取類型資訊的核心工具
Copyright ©
程式碼之家 All Rights Reserved