C# 提供兩種定義常數的方式:const(編譯期常數)與 readonly(執行期常數)。兩者在記憶體模型、型別限制、版本相容性上有本質差異。本文深度解析並給出選擇建議。
public const int MaxValue = 10;
// 隱含 static,等同於
public static const int MaxValue = 10; // 語法錯誤,僅示意
int, double, string, enum 等),不可為參考型別(除 string),不可用 new 建構。ldc.i4.10),無記憶體配置。const 值,呼叫端未重新編譯仍使用舊值 → 行為不一致。
public readonly int MaxValue = 10;
// 或在建構函式指派
public readonly int MaxValue;
public MyClass() => MaxValue = 10;
ldsfld/ldfld)。| 特性 | const | readonly |
|---|---|---|
| 初始化時機 | 宣告時 | 宣告時或建構函式 |
| 型別限制 | 僅實質型別 | 無限制 |
| 記憶體 | 無(IL 內嵌) | 有(欄位儲存) |
| 存取速度 | 極快(常值) | 快(欄位讀取) |
| 版本相容 | 需重編譯呼叫端 | 無需重編譯 |
| 適用對象 | 絕對不變的常值(如 Math.PI) | 組態值、執行期決定的常數 |
// Lib.dll v1.0
public const int MaxConnections = 10;
// App.exe 編譯時內嵌 10
int limit = MaxConnections; // IL: ldc.i4.10
// Lib.dll v1.1 修改為 20
// App.exe 不重編譯直接執行 → limit 仍為 10 → Bug!
改用 readonly 則無此問題。
const。readonly。readonly,除非確定為基本型別且永不變更。const 與 readonly 的核心差異在於編譯期 vs 執行期。理解版本相容性陷阱,並在架構層級制定常數定義規範,能避免難以追蹤的部署 Bug。