首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

Effective C# 原則 2:選擇 readonly 而非 const 定義常數

     編輯:關於C#

C# 提供兩種常數機制:編譯時期常數(const)與執行時期常數(readonly)。兩者行為差異極大,使用不當將影響效能或導致版本相容性問題。原則是:寧可選擇稍慢但正確的執行時期常數,不可選擇快但易錯的編譯時期常數。

核心差異:值的替換時機

  • const(編譯時期常數):編譯器會將所有引用處直接替換為常數值。例如 if (year == _Millennium) 編譯後等同於 if (year == 2000)。IL 中不保留欄位引用,只保留字面值。
  • readonly(執行時期常數):值在建構函式或靜態建構函式中決定,執行時期透過欄位引用存取。IL 會產生 ldsfld 指令載入欄位值,而非硬編碼常數。

型別限制

const 僅限於基本型別(整數、浮點數)、string、enum。無法使用 new 運算子初始化(即使是值型別如 DateTime)。readonly 則可為任意型別,且必須在建構函式中初始化,支援執行時期計算的值。

實例 vs 靜態

  • const 隱含 static,只能是類別層級常數。
  • readonly 可為實例欄位(每個實例擁有不同值)或靜態欄位。

跨組件版本控管的關鍵差異

假設組件 Infrastructure 定義:

public class UsefulValues {
    public static readonly int StartValue = 5;
    public const int EndValue = 10;
}

客戶端組件引用並編譯:

for (int i = UsefulValues.StartValue; i < UsefulValues.EndValue; i++) ...

後來 Infrastructure 更新為 StartValue = 105, EndValue = 120,僅重新部署 Infrastructure 而不重新編譯客戶端:

  • StartValue(readonly):客戶端執行時動態載入新值 105,行為正確。
  • EndValue(const):客戶端 IL 中已硬編碼為 10,迴圈仍以 10 為終止條件,行為錯誤。

結論:更新 const 屬於介面變更,必須重新編譯所有呼叫端;更新 readonly 屬於實作變更,二進位相容。

何時使用 const?

  • 屬性參數(Attribute 參數)
  • Enum 定義
  • 絕不會隨版本變更的基礎常數(如版本號常數 VERSION_1_0 = 0x0100)

即使如此,預設仍建議使用 readonly,除非效能分析證實 const 有顯著優勢(通常差異微乎其微)。

最佳實踐範例

// 編譯時期常數:固定版本識別碼
private const int VERSION_1_0 = 0x0100;
private const int VERSION_2_0 = 0x0200;

// 執行時期常數:目前版本,隨發布更新
private static readonly int CURRENT_VERSION = VERSION_2_0;

// 序列化時寫入目前版本(執行時期值)
inf.AddValue("VERSION", CURRENT_VERSION);

// 反序列化時比對編譯時期常數
switch (storedVersion) {
    case VERSION_2_0: ... break;
    case VERSION_1_0: ... break;
}

總結

優先使用 readonly 獲得版本相容性與彈性;僅在語法強制或極致效能需求下使用 const。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved