在 C# 中定義常數主要有兩種關鍵字:const(編譯期常數)與 readonly(執行期常數)。雖然都能讓數值不可變,但其底層機制、適用場景與限制差異極大。
public const int MAX_VALUE = 10;
static,屬於類別而非實例。編譯時直接將常數值內嵌至呼叫端的 IL 碼中。new 初始化;不支援參考型別(除 string 外)。public readonly int MAX_VALUE = 10;
// 或在建構函式指派
public readonly int MAX_VALUE;
public MyClass() { MAX_VALUE = 10; }
| 維度 | const (編譯期) | readonly (執行期) |
|---|---|---|
| 初始化時機 | 宣告時必須指定 | 宣告時或建構函式 |
| 型別限制 | 僅值型別 + string | 無限制 |
| 實例關係 | 所有實例共享同一值 | 每個實例可有不同值 |
| 記憶體開銷 | 無 (內嵌 IL) | 有 (欄位儲存) |
| 跨 DLL 版本安全 | 否 (需重新編譯呼叫端) | 是 |
| 效能 | 極高 | 略低 |
假設類庫 MyLib.dll 定義:
// 版本 1.0
public const int MAX_RETRY = 3;
呼叫端編譯後,IL 碼變成 int retry = 3;。若類庫升級為 2.0 並修改常數:
// 版本 2.0
public const int MAX_RETRY = 5;
呼叫端不重新編譯直接執行,仍使用舊值 3,導致邏輯錯誤。改用 readonly 則無此問題。
Math.PI 風格)。「為了避免版本控管噩夢,現代 C# 開發強烈建議:公開常數請用 readonly,私有效能常數才考慮 const。」