程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> const,readonly 這些你真的懂嗎? 也許會被面試到哦。。。,constreadonly

const,readonly 這些你真的懂嗎? 也許會被面試到哦。。。,constreadonly

編輯:C#入門知識

const,readonly 這些你真的懂嗎? 也許會被面試到哦。。。,constreadonly


 

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

怕了。既然說到了原理,我們還是從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 用來自計算堆棧的值替換靜態字段的值。


const與readonly究竟有什不同?

const:
不能是靜態的;
值是在編譯時規定的;
只能在declaration時候賦值;
readonly:
可以是靜態的也可以是不靜態的;
值是到運行時才規定的;
可以在declaration時候賦值,也可以在constructor裡賦值。
 

const與readonly的不同舉例說明

const和readonly這兩個關鍵詞在很多環境裡都用到,你沒說你用在什麼環境中。多數情況下const用來定義常量,就是說程序在運行時都不會去修改用const來聲明的東東(其實也沒法改,否則編譯都通不過),readonly多數是某些編輯輸入框之類的控件的屬性,表明這個框裡的文字是無法通過用戶操作來修改的,但是程序在運行態是可以隨時修改這些文本的內容的。
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved