2017年9月8日 星期五

.NET C# 常數 const 與 唯讀 readonly

常數 const 與 唯讀 readonly 在應用程式執行上,所表現出來的最終行為是一樣的,那就是這兩個物件的值,在執行時期是無法變更的;可是,對於這兩種類型的物件的內在特型與執行時候的 IL 程式碼,卻有著處理上的很大不同。

了解更多關於 [const 關鍵字
了解更多關於 [readonly 關鍵字
了解更多關於 [C# 程式設計手冊

在這裡,我們宣告了一個類別,這個類別裡面只有兩個成員,一個是 const 的整數欄位成員,另外一個是 readonly 的整數常數欄位成員。
我們可以從微軟官方的文件中看到底下敘述
欄位會在呼叫物件執行個體的建構函式之前立即初始化。 如果建構函式指派了欄位的值,該值會覆寫欄位宣告期間所指定的任何值。
所以,在我們這個範例中,並沒有建置建構函式,而是提供了欄位的初始化設定,讓這兩個欄位擁有預先設定的內容。
    public class MyClass
    {
        public const int MyConstantString = 15;
        public readonly int MyReadonlyString = 168;
    }
接著,我們建立了 MyClass 這個類別物件,myObject,接著要來存取這個類別內的常數與唯讀欄位,此時,就會看到這兩者欄位的其中一個不同點。
當您在類別內宣告了一個常數欄位,這個常數欄位就具備了靜態特性,也就是說,我們要存取常數欄位,需要使用 類別名稱.欄位名稱 的方式來存取;而唯讀欄位則是透過執行個體才能夠存取,就是,在每個執行個體內,都會有這樣一個欄位,它是屬於唯讀的(這個欄位的值,需要在建構函式內進行初始化或者可以在宣告欄位時,使用指派運算子來指定欄位的初始值)
            MyClass myObject = new MyClass();

            int tmpString = MyClass.MyConstantString;
            tmpString = myObject.MyReadonlyString;
最後我們來看看進行存取常數欄位的 IL 中繼語言程式碼和唯讀欄位的 IL 中繼語言程式碼
這個是常數 IL 中繼語言程式碼,我們可以看到,我們要把常數整數 15 設定到變數 tmpString 內;因為這個是常數欄位,所以,編譯器直接把 15 這個整數值,轉換到 IL 中繼語言程式碼上了。
mov dword ptr [ebp-44h], 0Fh

這個是唯讀 IL 中繼語言程式碼,編譯器要透過位置定位方式,指出欄位 myObject.MyReadonlyString 所儲存的整數值為多少,這樣才能夠取出這個整數值,並且設定到 tmpString 變數內。
move eax,dword ptr [epb-40h]

了解更多關於 [const 關鍵字
了解更多關於 [readonly 關鍵字
了解更多關於 [C# 程式設計手冊

沒有留言:

張貼留言