[轉]const 與 readonly知多少

引自http://www.cnblogs.com/royenhome/archive/2010/05/22/1741592.htmlhtml

儘管你寫了不少年的C#的代碼,可是可能當別人問到你const與readonly的區別時候,仍是會小小的愣一會吧~程序員

      筆者也是在看歐立奇版的《.Net 程序員面試寶典》的時候,才發現本身長久以來居然在弄不清出二者的狀況下,混用了這麼長的時間。的確,const與readonly 很像,都是將變量聲明爲只讀,且在變量初始化後就不可改寫。那麼,const與readonly 這兩個修飾符到底區別在什麼地方呢?其實,這個牽扯出C#語言中兩種不一樣的常量類型:靜態常量(compile-time constants)和動態常量(runtime constants)。這二者具備不一樣的特性,錯誤的使用不只會損失效率,並且還會形成錯誤。面試

      首先先解釋下什麼是靜態常量以及什麼是動態常量。靜態常量是指編譯器在編譯時候會對常量進行解析,並將常量的值替換成初始化的那個值。而動態常量的值則是在運行的那一刻纔得到的,編譯器編譯期間將其標示爲只讀常量,而不用常量的值代替,這樣動態常量沒必要在聲明的時候就初始化,而能夠延遲到構造函數中初始化。函數

      當你大體瞭解上面的兩個概念的時候,那麼就能夠來講明const與readonly了。const修飾的常量是上述中的第一種,即靜態常量;而readonly則是第二種,即動態常量。那麼區別能夠經過靜態常量與動態常量的特性來講明:工具

      1)const修飾的常量在聲明的時候必須初始化;readonly修飾的常量則能夠延遲到構造函數初始化 this

      2)const修飾的常量在編譯期間就被解析,即常量值被替換成初始化的值;readonly修飾的常量則延遲到運行的時候spa

      此外const常量既能夠聲明在類中也能夠在函數體內,可是static readonly常量只能聲明在類中。3d

      

      可能經過上述純概念性的講解,對有些初學者有些暈乎。下面就一些例子來講明下:      code

複製代碼
using  System; class  P {      static   readonly   int  A = B * 10 ;      static   readonly   int  B = 10 ;         public   static   void  Main( string [] args)     {         Console.WriteLine( " A is {0},B is {1}  " ,A,B);     } }
複製代碼

 

      對於上述代碼,輸出結果是多少?不少人會認爲是A is 100,B is 10吧!其實,正確的輸出結果是A is 0,B is 10。好吧,若是改爲下面的話:orm

複製代碼
using  System; class  P {      const   int  A = B * 10 ;      const   int  B = 10 ;         public   static   void  Main( string [] args)     {         Console.WriteLine( " A is {0},B is {1}  " ,A,B);     } }
複製代碼

 

       對於上述代碼,輸出結果又是多少呢?難道是A is 0,B is 10?其實又錯了,此次正確的輸出結果是A is 100,B is 10。

       那麼爲何是這樣的呢?其實在上面說了,const是靜態常量,因此在編譯的時候就將A與B的值肯定下來了(即B變量時10,而A=B*10=10*10=100),那麼Main函數中的輸出固然是A is 100,B is 10啦。而static readonly則是動態常量,變量的值在編譯期間不予以解析,因此開始都是默認值,像A與B都是int類型,故都是0。而在程序執行到A=B*10;因此A=0*10=0,程序接着執行到B=10這句時候,纔會真正的B的初值10賦給B。若是,你仍是不大清楚的話,咱們能夠藉助於微軟提供的ILDASM工具,只需在Vs 2008 Command下輸入ILDASM就能夠打開,以下所示:

        

        

        分別打開上述兩個代碼編譯後產生的可執行文件,以下圖所示:

                       

                   static readonly可執行程序的結構                                                                const可執行程序的結構

 

        在上述兩張圖中均可以看到A與B常量,分別雙擊節點能夠看出其中的差別:

              

                   static readonly修飾的常量A                                                                      const修飾的常量A

    

           

                  static readonly修飾的常量B                                                                       const修飾的常量B

 

         從上圖中能夠看出,const修飾的常量在編譯期間便已將A,B的字面值算出來了,而static readonly修飾的常量則未解析,因此在Main函數中有如下的區別:

                    

                              static readonly程序的Main函數                                                            const程序的Main函數

 

      從Main函數中咱們能夠看出,const的那個程序的輸出直接是100與10,而readonly在輸出的時候確實P::A與P::B,即將A與B常量的值延遲到運行的時候纔去肯定,故輸出是0與10。

      那麼對於靜態常量以及動態常量還有什麼特性呢?其實,靜態常量只能被聲明爲簡單的數據類型(int以及浮點型)、枚舉、布爾或者字符串型,而動態常量則除了這些類型,還能夠修飾一些對象類型。如DateTime類型,以下:

      //錯誤

      const DateTime time=new DateTime(); 

      //正確

      static readonly DateTime time=new DateTime();

 

     上述錯誤在於不能使用new關鍵字初始化一個靜態常量,即使是一個值類型,由於new將會致使到運行時才能肯定值,與靜態變量編譯時就肯定字面值有悖。     

      歐書上最後給出了對靜態常量與動態常量之間的比較,以下表所示:      

      

      

       最近隨筆較少,但願這篇能給一些朋友帶來一些幫助~ 

相關文章
相關標籤/搜索