const:表示常量,變量的值是絕不會被改變的,常量的值是在編譯時就已經確定了。編譯器會把常量的值保存在程序集的元素據里面,在C#里面,下面列舉的簡單類型才能被定義為 常量:Boolean, Char, Byte, SByte, Int16, UInt16 , Int32, UInt32 , Int64, UInt64 , Single , Double , Decimal, String。如果定一個引用類型為常量,則必須把該變量的值設為null。因為常量的值是不會改變的,所以常量也常常被認為是定義的類型的一部分。換句話說,常量通常也是靜態的。當定義一個常量符號,編譯器會在程序集的元素據里面查找它的值,並把值嵌入到生成的IL里面,也因此在運行時,常量不需要分配任何內存。當然,也不能獲取常量的地址以及通過引用的方式傳遞常量。這些限制讓常量不能很好的跨程序集版本。
例如:
namespace TypeTest { public sealed class SomeLibType { public const Int32 MaxEntriesInList = 50; } public sealed class Program { public static void Main() { Console.WriteLine("最大的整型的數值為:" + SomeLibType.MaxEntriesInList); } } }
查看下Main部分的IL代碼可以清楚知道常量的值已經嵌入在IL代碼里面了,如下:
其實我們還可以看看關於定義的MaxEntriesInList,之前有說過常量一般也是靜態的,如下:
static:表示類型狀態的一部分,靜態意味着共享。相對於C++,C#里面沒有全局函數和全局變量的概念,等效的是使用靜態。兩者在功能上沒有什么差異,只是靜態字段和方法可以使用訪問修飾符。靜態類對應的IL會自動標記為abstract和sealed。
readonly:只有在構造函數里面才能改變它的值,只能用於字段,不能用於局部變量。修飾數組時,不會凍結數組的內容,只會凍結數組的元素數量,因為無法將只讀字段賦值為一個新的實例。不過,數組中的單個元素是可寫的。
volatile:編譯器或CPU有時會對代碼進行優化,是指令不按照它們編碼的順序執行,或者干脆拿掉一些無用的指令。若代碼在一個線程上執行,這樣的優化沒有什么影響。如果在多線程環境下,就肯能造成出乎意料的效果。這時可以使用volatile來強迫所有的讀寫操作按照代碼指定的順序發生。
注 《CLR via C#》(Jeffrey Richter著)——.NET 界的經典之作,讀的過程寫點筆記跟大家分享,我也推薦大家看英文版,能夠直接領會原意