深入探討C#中的const、readonly關(guān)鍵字
首先不可否認(rèn),這些在面試上會經(jīng)常被面試官問起,但是你回答的讓面試官滿意嗎?當(dāng)然如果你知道了這些原理,或許你就不
怕了。既然說到了原理,我們還是從MSDN說起。
一:值得推敲的幾個地方
1.先來看看msdn上面對const是怎么說的,我們會看到。不能修改,編譯時(shí)常量這些關(guān)鍵性信息。
Q: const為什么不能被修改。
A:這個很簡單,很多教科書上面都說,當(dāng)編譯器編譯時(shí),會將常量的值保存在該程序集的元數(shù)據(jù)中,下面我們做個實(shí)例
看一看。
①:新建一個projectA。
// ProjectA
public class TestClass
{
public const int CTRIP = int.MaxValue;
}
再建一個MainProject,引用下projectA。
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine(TestClass.CTRIP);
Console.Read();
}
}
然后我們把mainproject運(yùn)行起來。
既然我把mainproject跑起來了,并且也引用了Test.dll,剛才也說了,編譯的時(shí)候會把常量值保存在程序集的元數(shù)據(jù)中,那我們
就找一找,打開ILdasm.exe,并且Ctrl+M。
很可惜,我并沒有找到Ctrip的符號,也沒有找到int.MaxValue,也沒有找到所謂的0x7fffffff,倒是找到了一個Assembly的一些版本信息的元數(shù)據(jù),那么這時(shí)候你可能會疑惑了,究竟const的值有沒有保存到Assembly里面去呢?很簡單的一個驗(yàn)證方法就是,把Mainproject下面bin中的Test.dll刪除掉,看看會有怎么樣的奇跡發(fā)生。
②: 聰明的你應(yīng)該想到了,既然運(yùn)行Demo.exe的時(shí)候不再加載Test.dll,而是直接從Demo的Assembly里面獲取const值,
那是不是會有斷層的事情發(fā)生,也就是版本不一致的情況,比如我已經(jīng)修改了const值,然后把編譯好的dll拷貝到Mainproject的bin目錄下,直接運(yùn)行Demo.exe,會不會出現(xiàn)MainProject讀不到修改后的const值呢?這里我將const改成 int.MinValue。
下面我們可以試試看。
// ProjectA
public class TestClass
{
public const int CTRIP = int.MinValue;
}
好了,看到上面的結(jié)果,就進(jìn)一步佐證了剛才的說法,const確確實(shí)實(shí)是保存在Assembly的元數(shù)據(jù)中,這里還要順便提示一下,Enum本質(zhì)上是const,所以它也存在我剛才說的斷層的問題,說到這里,我想你對const的原理應(yīng)該比較熟悉了,現(xiàn)在我們來看看Question的問題。既然是元數(shù)據(jù),那什么是元數(shù)據(jù)?“描述數(shù)據(jù)的數(shù)據(jù)” 叫做元數(shù)據(jù),既然它是基礎(chǔ)的描述性數(shù)據(jù),那么在定義好后是決對不能改變的,這個定義時(shí)也就是msdn說的編譯時(shí),是不是so easy呢?
Q: const為什么要做成靜態(tài)的,而不是做成實(shí)例的
A: 其實(shí)通過對第一個Question的分析,很多東西我們應(yīng)該都會豁然開朗,因?yàn)榇嬖跀鄬拥膯栴},那么最好的方法就是const的值
永遠(yuǎn)也不要變,這樣就可以避免問題的發(fā)生,既然是永遠(yuǎn)都不變的東西,當(dāng)然是跟著“類型”走比跟著“實(shí)例”走要好的多,你說對不對,因?yàn)閟tatic是個小緩存,沒必要new一下才產(chǎn)生。。。
Q: readonly字段只能在ctor中初始化嗎?
A:這個問題蠻有意思的,我們知道readonly的意思就是只讀字段的意思,我們知道一般的字段具有可讀寫的功能,
先還是看看編譯器怎么說。
從編譯器上可以看到,確實(shí)readonly的初始化還可以在“變量初始化”的時(shí)候進(jìn)行初始化,那么這樣說Question的答案應(yīng)該就是否定的,但是真的是如此嗎?我們都知道有一個東西叫做“語法糖”,而且經(jīng)常是編譯器提供給我們用的,所以真正的想看到發(fā)生了什么,只能用ILDasm.exe 穿透編譯器,看看到底發(fā)生了什么。
從IL中可以看到,真的就是編譯器的語法糖,本質(zhì)上都是在ctor中初始化的,所以說,看問題千萬不要看表面。
注:Stsfld 用來自計(jì)算堆棧的值替換靜態(tài)字段的值。
相關(guān)文章
基于C#實(shí)現(xiàn)一個溫濕度監(jiān)測小工具
這篇文章主要為大家詳細(xì)介紹了如何基于C#實(shí)現(xiàn)一個溫濕度監(jiān)測小工具,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下2023-01-01詳解C# 泛型中的數(shù)據(jù)類型判定與轉(zhuǎn)換
這篇文章主要介紹了C# 泛型中的數(shù)據(jù)類型判定與轉(zhuǎn)換,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07深入理解C# abstract和virtual關(guān)鍵字
深入理解C# abstract和virtual關(guān)鍵字,學(xué)習(xí)c#的朋友可以參考下。2011-06-06C#連接SQL?Sever數(shù)據(jù)庫詳細(xì)圖文教程
C#是Microsoft公司為.NET Framework推出的重量級語言,和它搭配最完美的數(shù)據(jù)庫無疑就是Microsoft SQL Server了,下面這篇文章主要給大家介紹了關(guān)于C#連接SQL?Sever數(shù)據(jù)庫的詳細(xì)圖文教程,需要的朋友可以參考下2023-06-06insert語句太長用StringBuilder優(yōu)化一下
insert語句太長用StringBuilder優(yōu)化一下,下面是示例代碼,需要的朋友可以研究研究2014-07-07C#實(shí)現(xiàn)漢字轉(zhuǎn)漢語拼音的示例代碼
這篇文章主要介紹了如何利用C#實(shí)現(xiàn)漢字轉(zhuǎn)漢語拼音,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C#有一定幫助,感興趣的小伙伴可以跟隨小編一起動手試一試2022-03-03