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

C# 常數完整指南:const/readonly、字面值、列舉、編譯期與執行期常數差異

     編輯:C# 入門

C# 常數完整指南:const/readonly、字面值、列舉、編譯期與執行期常數差異

常數 是編譯後不可變更的固定值。C# 提供 const (編譯期常數) 與 readonly (執行期常數) 兩種機制,另有字面值、列舉常數。正確選擇能確保效能、版本相容性與語意正確。

const:編譯期常數

const 欄位/區域變數在編譯期確定值,IL 中直接內嵌常數值:

public const double PI = 3.141592653589793;
public const int MaxRetries = 3;
public const string AppName = "MyApp";

// 區域常數
const int BufferSize = 4096;

// 必須初始化,且初始化運算式必須為編譯期常數
// const DateTime Now = DateTime.Now; // 錯誤:非編譯期常數
// const int[] Arr = {1,2,3}; // 錯誤:陣列非常數

特性與限制

  • 隱含 static,不可標示 static
  • 型別限制:bool、byte、sbyte、short、ushort、int、uint、long、ulong、char、float、double、decimal、string、enum、null (參考型別僅限 null)
  • 跨組件使用:呼叫端組件編譯時內嵌常數值,若常數值變更需重新編譯呼叫端
  • 適合:真正永不變更的值 (數學常數、固定限制、協定版本)

readonly:執行期常數

readonly 欄位在建構子或宣告處初始化,之後不可變更:

public class Config {
    // 宣告初始化
    public readonly string Version = "1.0.0";
    
    // 建構子初始化 (可依參數決定)
    public readonly int MaxConnections;
    public readonly DateTime StartupTime;
    
    public Config(int maxConn) {
        MaxConnections = maxConn;
        StartupTime = DateTime.UtcNow; // 執行期取得
    }
    
    // readonly 靜態欄位:靜態建構子初始化
    public static readonly string ConnectionString;
    static Config() {
        ConnectionString = LoadFromConfigFile(); // 複雜初始化
    }
}

特性

  • 可為實例或靜態欄位
  • 型別無限制 (任意型別)
  • 執行期解析,跨組件不內嵌值,修改值只需重新編譯定義組件
  • 適合:執行期才能決定、或可能變更的「常數」(設定值、資源路徑、單例實例)

const vs readonly 快速選擇

場景選擇原因
數學常數 (PI, E)const永不變更、編譯期可知、效能最佳
應用程式版本號readonly建置時期注入、可能更新
資料庫連線字串readonly執行期從設定檔讀取
介面中的常數const介面不支援 readonly 欄位 (C# 8 前)
屬性參數const屬性建構子需編譯期常數
大型陣列/集合readonlyconst 不支援陣列
跨組件共用、可能變更readonly避免重新編譯消費者

字面值

整數字面值

int dec = 42;
uint u = 42U;
long l = 42L;
ulong ul = 42UL;
long hex = 0x2A;       // 十六進位
long bin = 0b101010;   // 二進位 (C# 7+)
int underscore = 1_000_000; // 數字分隔符 (C# 7+)

// 後綴大小寫皆可:42u 42U 42l 42L

浮點字面值

double d = 3.14;
float f = 3.14F;       // F/f 後綴
decimal m = 3.14M;     // M/m 後綴
double sci = 1.23e-4;  // 科學記號
double hexFloat = 0x1.921fb54442d18p+1; // 十六進位浮點 (C# 11+)

字元與字串字面值

char c = 'A';
char newline = '\n';
char unicode = '\u0041';    // Unicode 逸出
char hexChar = '\x41';      // 十六進位

string s1 = "Hello";
string s2 = @"C:\Path\File"; // 逐字字串:不處理逸出、可跨行
string s3 = $"{DateTime.Now}"; // 插值字串

// 逐字字串雙引號逸出
string quote = @"""Hello"""; // "Hello"

列舉常數

列舉成員本質為編譯期常數,底層為整數型別:

public enum HttpStatus : int {
    OK = 200,
    NotFound = 404,
    ServerError = 500
}

// 使用如常數
int code = HttpStatus.OK; // 200
// switch 窮盡性檢查
string msg = status switch {
    HttpStatus.OK => "成功",
    HttpStatus.NotFound => "找不到",
    _ => "其他"
};

進階主題

readonly struct 與 init 存取子

// C# 9+ init 存取子:物件初始化器可設定,之後不可變
public class Settings {
    public string ApiKey { get; init; }
    public int Timeout { get; init; }
}

// 使用
var s = new Settings { ApiKey = "key", Timeout = 30 };
// s.ApiKey = "new"; // 編譯錯誤

required 成員

// C# 11+:建構/初始化時必須提供
public class User {
    public required string Email { get; init; }
    public required string Name { get; init; }
}
var u = new User { Email = "a@b.com", Name = "Alice" };

常數運算式與屬性

[SomeAttribute(MaxRetries)] // 需 const
public class MyClass { }

const int MaxRetries = 3; // 編譯期常數

最佳實踐

  • 預設用 readonly:除非確定永不變更且為基本型別/字串/enum,才用 const。
  • 公開 API 常數用 readonly:避免消費者重新編譯地獄。
  • 命名慣例:PascalCase (public/protected),camelCase (private/區域)。
  • 分組相關常數:用 static class 或 enum 組織。
  • 避免魔術數字:即使區域變數也用 const/readonly 命名。
  • 數值分隔符:1_000_000 提升可讀性。

常見問題 FAQ

Q: 為什麼 const 跨組件會有版本問題?

A: 編譯器將常數值直接寫入呼叫端 IL。定義組件修改 const 值重新編譯,呼叫端若不重新編譯仍使用舊值。

Q: readonly 欄位可以用物件初始化器嗎?

A: 不可以。readonly 欄位只能在宣告或建構子初始化。用 init 存取子 (屬性) 支援物件初始化器。

Q: const 可以是 null 嗎?

A: 參考型別 const 僅能為 null:const string Empty = null;。實值型別不可為 null。

Q: 什麼是「編譯期常數運算式」?

A: 僅由字面值、const 變數、基本運算子 (+ - * / % << >> & | ^ ~)、轉型、sizeof、預設值運算子組成的運算式。

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