文章出處

 

  首先不可否認,這些在面試上會經常被面試官問起,但是你回答的讓面試官滿意嗎?當然如果你知道了這些原理,或許你就不

怕了。既然說到了原理,我們還是從MSDN說起。

     

一:值得推敲的幾個地方

 1.先來看看msdn上面對const是怎么說的,我們會看到。不能修改,編譯時常量這些關鍵性信息。

 

Q:  const為什么不能被修改。

 

A:這個很簡單,很多教科書上面都說,當編譯器編譯時,會將常量的值保存在該程序集的元數據中,下面我們做個實例

     看一看。

 

   ①:新建一個projectA。

1 // ProjectA
2 public class TestClass
3 {
4     public const int CTRIP = int.MaxValue;
5 }

   再建一個MainProject,引用下projectA。

 1 using System;
 2 
 3 class Program
 4 {
 5     static void Main(string[] args)
 6     {
 7         Console.WriteLine(TestClass.CTRIP);
 8 
 9         Console.Read();
10     }
11 }

    然后我們把mainproject運行起來。

 

    既然我把mainproject跑起來了,并且也引用了Test.dll,剛才也說了,編譯的時候會把常量值保存在程序集的元數據中,那我們

就找一找,打開ILdasm.exe,并且Ctrl+M。

 

 

   很可惜,我并沒有找到Ctrip的符號,也沒有找到int.MaxValue,也沒有找到所謂的0x7fffffff,倒是找到了一個Assembly

的一些版本信息的元數據,那么這時候你可能會疑惑了,究竟const的值有沒有保存到Assembly里面去呢?很簡單的一個驗證

方法就是,把Mainproject下面bin中的Test.dll刪除掉,看看會有怎么樣的奇跡發生。

 

 

  這時候你會發現,既然test.dll都刪除了。Demo.exe既然還能運行起來,說明const的值真的是寫入到了Assembly里面

去了。不然值從哪里來的呢?

 

 ②: 聰明的你應該想到了,既然運行Demo.exe的時候不再加載Test.dll,而是直接從Demo的Assembly里面獲取const值,

       那是不是會有斷層的事情發生,也就是版本不一致的情況,比如我已經修改了const值,然后把編譯好的dll拷貝到Mainproject

       的bin目錄下,直接運行Demo.exe,會不會出現MainProject讀不到修改后的const值呢?這里我將const改成 int.MinValue。

       下面我們可以試試看。

1 // ProjectA
2 public class TestClass
3 {
4     public const int CTRIP = int.MinValue;
5 }

    

 

好了,看到上面的結果,就進一步佐證了剛才的說法,const確確實實是保存在Assembly的元數據中,這里還要順便提示

一下,Enum本質上是const,所以它也存在我剛才說的斷層的問題,說到這里,我想你對const的原理應該比較熟悉了,現

在我們來看看Question的問題。既然是元數據,那什么是元數據?“描述數據的數據” 叫做元數據,既然它是基礎的描述性

據,那么在定義好后是決對不能改變的,這個定義時也就是msdn說的編譯時,是不是so easy呢?

 

Q:  const為什么要做成靜態的,而不是做成實例的

 

A:  其實通過對第一個Question的分析,很多東西我們應該都會豁然開朗,因為存在斷層的問題,那么最好的方法就是const的值

      永遠也不要變,這樣就可以避免問題的發生,既然是永遠都不變的東西,當然是跟著“類型”走比跟著“實例”走要好的多,你說

      對不對,因為static是個小緩存,沒必要new一下才產生。。。

 

Q: readonly字段只能在ctor中初始化嗎?

 

 

A:這個問題蠻有意思的,我們知道readonly的意思就是只讀字段的意思,我們知道一般的字段具有可讀寫的功能,

     先還是看看編譯器怎么說。

 

  從編譯器上可以看到,確實readonly的初始化還可以在“變量初始化”的時候進行初始化,那么這樣說Question的答案

應該就是否定的,但是真的是如此嗎?我們都知道有一個東西叫做“語法糖”,而且經常是編譯器提供給我們用的,所以

真正的想看到發生了什么,只能用ILDasm.exe 穿透編譯器,看看到底發生了什么。

 

從IL中可以看到,真的就是編譯器的語法糖,本質上都是在ctor中初始化的,所以說,看問題千萬不要看表面。

 

注:Stsfld 用來自計算堆棧的值替換靜態字段的值。


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜

    大師兄 發表在 痞客邦 留言(0) 人氣()