| 特性 | const | static readonly |
|---|---|---|
| 值確定時機 | 編譯期 (必須為常數運算式) | 執行期 (靜態建構函式或宣告初始化) |
| 允許型別 | 基本型別、string、enum、null 參考 | 任意型別 (含陣列、類別實例、結構) |
| 記憶體 | 不佔用儲存空間,值內嵌至呼叫端 IL | 儲存於型別靜態欄位,佔用記憶體 |
| 跨組件版本 | 修改值需重編譯所有參考組件 | 修改值僅需重編譯定義組件 |
| 可用位置 | 欄位、區域變數 | 僅限欄位 (不可用於區域變數/屬性) |
// 1. new 物件 -> 僅 static readonly
static readonly MyClass Obj1 = new MyClass(); // const 不可 (需執行建構函式)
// 2. null 參考 -> 兩者皆可
static readonly MyClass Obj2 = null;
const MyClass Obj3 = null; // 僅參考型別允許 null
// 3. 常數運算式 -> 兩者皆可
static readonly int A = B * 20;
static readonly int B = 10;
const int C = B * 20; // OK
// 4. 陣列/集合初始化 -> 僅 static readonly
static readonly int[] Primes = new int[] {2,3,5}; // const 不可
// 5. 區域變數 -> 僅 const
void Foo() { const int LocalConst = 10; /* static readonly 不可用於區域 */ }
const 無法建構物件,static readonly 是標準做法:
public class Color
{
public static readonly Color Black = new Color(0, 0, 0);
public static readonly Color White = new Color(255, 255, 255);
public static readonly Color Red = new Color(255, 0, 0);
public static readonly Color Green = new Color(0, 255, 0);
public static readonly Color Blue = new Color(0, 0, 255);
private readonly byte _r, _g, _b;
public Color(byte r, byte g, byte b) { _r=r; _g=g; _b=b; }
}
static readonly` 參考型別的可變性陷阱
public static readonly MyClass Instance = new MyClass();
// 合法:修改物件內部狀態
Instance.SomeProperty = 10;
// 非法:替換參考
Instance = new MyClass(); // 編譯錯誤:readonly 欄位不可指派
// 結構 (值型別) 不同:readonly 結構欄位連同內容皆不可變
public static readonly MyStruct S = new MyStruct();
// S.SomeField = 10; // 編譯錯誤:無法修改 readonly 結構的欄位
const。static readonly。const (唯一選項)。