const和readonly你真的懂嗎?


第二遍文章我打算把const和readonly的區別拿出來講下,因為寫代碼這么久我都還沒搞清楚這兩者的區別,實在有點慚愧,所以這一次我打算搞清楚它。

定義

來看看MSDN的解釋:

readonly:readonly關鍵字是可以在字段上使用的修飾符。當字段聲明包括readonly修飾符時,該聲明引入的字段賦值只能作為聲明的一部分,或者出現在同一類的構造函數中。

const使用 const 關鍵字來聲明某個常量字段或常量局部變量。 常量字段和常量局部變量不是變量並且不能修改

太多理論的講解有些人可能看了更犯暈,所以直接寫些代碼我覺得可能比較直觀好理解。

 

舉例

我們先來看下const

public class ConstTest
{
        class SampleClass
        {
            public int x;
            public int y;
            public const int c1 = 5;
            public const int c2 = c1 + 5;
            public static const int z=8;    //這個寫法錯誤,因為const是靜態常量,可看下面提供c1的IL語言圖片。
 
         
            //變量可以在這里初始化值,但是如果把const放在這里初始化,編譯會出錯(賦值號左邊必須為變量、屬性或索引器)
            public SampleClass(int p1, int p2)
            {
                x = p1;
                y = p2;
            }
        }
        static void Main()
        {
            SampleClass mC = new SampleClass(11, 22);
            Console.WriteLine("x = {0}, y = {1}", mC.x, mC.y);
            Console.WriteLine("c1 = {0}, c2 = {1}",SampleClass.c1, SampleClass.c2);  //類型引用
        }
 }
/* Output
    x = 11, y = 22
    c1 = 5, c2 = 10
 */
來看下IL語言:
QQ截圖20151102230247
QQ截圖20151102230308

c2和y省略在這里省略,從上面的圖我們得出了一個結論:

那就是靜態常量,那什么是靜態常量呢?靜態常量是指編譯器在編譯時候會對常量進行解析,並將常量的值替換成初始化的那個值。即圖中里面的c1和c2,它們都是在編譯的時候值就確定下來(c1=5,c2=10),這個相信大家也比較好理解。

我們再來看readonly:

public class ReadOnlyTest
{
        class SampleClass
        {
            public readonly int x;
            public  readonly int y = 25;
            public  static readonly int z=12;
       
            //無參構造函數初始化readonly常量
            public SampleClass()
            {
                y = 24;
            }
            //靜態無參構造函數內初始化static readonly常量      
            static SampleClass()
            {
                z = 23;
            }
            //有參構造函數初始化readonly常量
            public SampleClass(int p1, int p2)
            {
                x = p1;
                y = p2;
            }
        }

        static void Main()
        {
            //訪問靜態成員
            Console.WriteLine(SampleClass.z);

            //訪問非靜態成員
            SampleClass p1 = new SampleClass(11, 21);   // OK
            Console.WriteLine("p1: x={0}, y={1}", p1.x, p1.y);
            SampleClass p2 = new SampleClass();
            Console.WriteLine("p2: x={0}, y={1}", p2.x, p2.y);

            Console.ReadKey();
        }
}
 /*
 Output:
 23
 p1: x=11, y=21
 p2: x=0, y=24
    */
同樣的,來看IL語言:
QQ截圖20151102230308

我們先看下什么是動態常量:

動態常量,是指值在運行的那一刻才獲得的,編譯器編譯期間將其標示為只讀常量,而不用常量的值代替,這樣動態常量不必在聲明的時候就初始化,而可以延遲到構造函數中初始化。

通過const和readonly的代碼我們可以得出以下結論:

1.readonly和static readonly定義的常量,指定初始值后(包括在構造函數內指定初始值)將不可更改,可讀不可寫。

2.static readonly常量,如果在構造函數內指定初始值,則必須是靜態無參構造函數,例如z參數的初始化過程。

3.const和static readonly定義的常量是靜態的,只能由類型直接訪問;而readonly定義的常量是非靜態的,只能由實例對象訪問。

const和readonly比較

1.const默認是靜態的,只能由類型訪問,不能和static同時使用,否則編譯錯誤;readonly默認是非靜態,由實例對象來訪問,可以顯式使用static定義為靜態成員。

2.const只能引用在值類型和string類型上,其他引用類型常量必須聲明為null,否則以new為const引用類型常量賦值,編譯器會提示錯誤,原因是構造函數初始化在運行時,而非編譯時;readonly只讀字段可以是任意類型,但是對於引用類型字段來說,readonly不能限制對該對象實例成員的讀寫控制。

3.const必須在字段聲明時初始化;而readonly可以在聲明時,或者構造函數中進行初始化,不同的構造函數可以為readonly常量實現不同的初始值

4.const可以定義字段和局部變量;而readonly則只能定義字段

5.const由於是靜態常量所以在編譯時會對常量進行解析,而readonly是動態常量在編譯期間編譯器將其標示為只讀常量,而不用常量的值代替,這樣就不必在聲明的時候就初始化,而可以延遲到構造函數中初始化

6.從應用角度來看,對於恆定不變且單獨使用的量來說,應該考慮聲明為const常量,例如性能比,百分比等;而對於可能隨實際運行發生變化的量,應該考慮聲明readonly常量,例如日期或時間,數據庫中的主鍵id等

 

以上內容希望對一些朋友帶來幫助~~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM