C#擁有兩種不同的常量:靜態常量(compile-time constants)和動態常量(runtime constants)。它們有不同的特性,錯誤的使用不僅會損失效率,還可能造成錯誤。相比之下,靜態常量在速度上會稍稍快一些,但是靈活性卻比動態常量差很多。
//靜態常量(隱式是靜態的)
public const int compiletimeConstant = 1;
//動態常量
public static readonly runtimeConstant = 1;
靜態常量在編譯時會將其替換為所對應的值,也就是說下面這2句話通過編譯器編譯後產生的IL是一樣的。
//通過編譯後二者會被翻譯成相同的中間語言
int myNum = compiletimeConstant;
int myNum = 1;
動態常量的值是在運行時獲得的。IL中將其標為只讀常量,而不是用常量的值代替。
靜態常量只能被聲明為簡單的數據類型(內建的int和浮點型)、枚舉或字符串。下面的程序段是通不過編譯的。你不能用new關鍵字初始化一個靜態常量,即便是對一個值類型來說。
//這樣是錯誤的
public const DateTime myDateTime = new DateTime(2006,9,1,0,0,0);
//這樣是可以的
public static readonly DateTime myDateTime = new DateTime(2006,9,1,0,0,0);
只讀數據也是常量的一種,它們不能在構造器初始化之後被修改。但是它同靜態常量不同,它的值是在運行時才被指派的,因此就會獲得更大的靈活性。動態常量可以是任意的數據類型。
二者最大的差別在於:靜態常量在編譯時會將其換為對應的值,這就意味著對於不同的程序集來說,當你改變靜態常量的時候需要將其重新編譯,否則常量的值不會發生變化,可能引發潛在的問題,而動態常量就不會有這種情況。
用const定義的常量(隱式是靜態的),需要像訪問靜態成員那樣去訪問const定義的常量,而用對象的成員方式去訪問會出編譯錯誤。 聲明的同時要設置常量值。
從另一方面來說,如果你的確要聲明一些從不改變且處處唯一的常量,例如鉤子函數SetWindowsHookEx的idHook參數或序列化時的版本等,就應該使用靜態常量。但是用到這樣的常量的機會不多。一般來說我們應該使用靈活性更高的動態常量。
靜態常量 動態常量
內存消耗 無 因為要保存常量 有消耗
初始化 很少的簡單類型, 任意類型,可以在類構造函數中賦值
不能new,必須在
聲明同時賦值
何時發揮作用 編譯時進行替換 相當於類中的數據成員