C#基本知識(shí)點(diǎn)-Readonly和Const的區(qū)別

目錄

什么是靜態(tài)常量(Const)和動(dòng)態(tài)常量(Readonly)

靜態(tài)常量(Const)和動(dòng)態(tài)常量(Readonly)之間的區(qū)別

動(dòng)態(tài)常量(Readonly)被賦值后不可以改變

總結(jié)

什么是靜態(tài)常量(Const)和動(dòng)態(tài)常量(Readonly)

先解釋下什么是靜態(tài)常量(Const)以及什么是動(dòng)態(tài)常量(Readonly)。

靜態(tài)常量(Const)是指編譯器在編譯時(shí)候會(huì)對(duì)常量進(jìn)行解析厢洞,并將常量的值替換成初始化的那個(gè)值。

動(dòng)態(tài)常量(Readonly)的值則是在運(yùn)行的那一刻才獲得的贡珊,編譯器編譯期間將其標(biāo)示為只讀常量瓶籽,而不用常量的值代替懒闷,這樣動(dòng)態(tài)常量不必在聲明的時(shí)候就初始化巩趁,而可以延遲到構(gòu)造函數(shù)中初始化。

靜態(tài)常量(Const)和動(dòng)態(tài)常量(Readonly)之間的區(qū)別

靜態(tài)常量(Compile-time Constant)動(dòng)態(tài)常量(Runtime Constant)

1.Const修飾的常量在聲明的時(shí)候必須初始化;Readonly修飾的常量則可以延遲到構(gòu)造函數(shù)初始化 脯燃。

2.Const常量既可以聲明在類中也可以在函數(shù)體內(nèi)搂妻,但是Static Readonly常量只能聲明在類中。Const是靜態(tài)常量辕棚,所以它本身就是Static的欲主,因此不能手動(dòng)再為Const增加一個(gè)Static修飾符。

3.Const修飾的常量在編譯期間就被解析逝嚎,即:經(jīng)過編譯器編譯后扁瓢,我們都在代碼中引用Const變量的地方會(huì)用Const變量所對(duì)應(yīng)的實(shí)際值來代替; Readonly修飾的常量則延遲到運(yùn)行的時(shí)候。

舉個(gè)例子來說明一下:


以上是語法方面的應(yīng)用补君,那在實(shí)際的用法上引几,還是有些微妙的變化,通常不易發(fā)覺.

舉個(gè)例子來說明一下:

在程序集DoTestConst.dll 中有一個(gè)類MyClass挽铁,定義了一個(gè)公開的靜態(tài)變量Count

publicstaticclassMyClass

{publicconstintCount =10;

}

然后另外一個(gè)應(yīng)用程序中引用DoTestConst.dll伟桅,并在代碼中作如下調(diào)用:

publicstaticvoidMain(string[] args)

{

Console.WriteLine(DoTestConst.MyClass.Count);//輸出10Console.ReadKey();

}

毫無疑問,非常簡(jiǎn)單的代碼叽掘,直接輸出10楣铁。

接下來更新MyClass的Count的值為20,然后重新編譯DoTestConst.dll更扁,并更新到應(yīng)用程序的所在目錄中盖腕,注意不要編譯應(yīng)用程序。那么這時(shí)候的輸出結(jié)果按預(yù)期那么想應(yīng)該是20才對(duì)疯潭,但實(shí)際上還是10赊堪,為什么呢?

這就是Const的特別之處竖哩,有多特別還是直接看生成的IL哭廉,查看IL代碼(假設(shè)這時(shí)候Count的值為10)

IL_0000: nop

IL_0001: ldc.i4.s 10

IL_0003: call void [mscorlib]System.Console::WriteLine(int32)

紅色代碼很明顯的表明了,直接加載10相叁,沒有通過任何類型的加載然后得到對(duì)應(yīng)變量的遵绰,也就是說在運(yùn)行時(shí)沒有去加載DoTestConst.dll,那么是否意味著沒有DoTestConst.dll也可以運(yùn)行呢增淹?答案是肯定的椿访,刪除DoTestConst.dll也可以運(yùn)行,是否很詭異呢虑润?也就解釋了之前的實(shí)驗(yàn)成玫,為什么更新Const變量的值之后沒有調(diào)用新的值,因?yàn)槌绦蛟谶\(yùn)行的時(shí)候根本不會(huì)去加載DoTestConst.dll。那么10這個(gè)值是從哪來的呢哭当?實(shí)際上CLR對(duì)于Const變量做了特殊處理猪腕,是將Const的值直接嵌入在生成的IL代碼中,在執(zhí)行的時(shí)候不會(huì)再去從dll加載钦勘。這也帶來了一個(gè)不容易發(fā)覺的Bug陋葡,因此在引用其他程序集的Const變量時(shí),需考慮到版本更新問題彻采,要解決這個(gè)問題就是把調(diào)用的應(yīng)用程序再編譯一次就ok了腐缤。但實(shí)際程序部署更新時(shí)可能只更新個(gè)別文件,這時(shí)候就必須用Readonly關(guān)鍵字來解決這個(gè)問題肛响。

接下來看Readonly的版本:

publicstaticclassMyClass

{publicstaticreadonlyintCount =10;

}

調(diào)用方代碼不變岭粤,接著看生成的IL代碼:

IL_0000: nop

IL_0001: ldsfld int32 [DoTestConst]DoTestConst.MyClass::Count

IL_0006: call void [mscorlib]System.Console::WriteLine(int32)

很明顯加載代碼變了,一個(gè)很常見的ldsfld動(dòng)作终惑,請(qǐng)求了DoTestConst.MyClass的Count變量绍在,是通過強(qiáng)制要求加載DoTestConst來實(shí)現(xiàn)的雹有。因此這時(shí)候更新Count的值重新編譯之后偿渡,還是不編譯調(diào)用程序,然后再執(zhí)行就會(huì)看到新的值霸奕。而這時(shí)候如果刪除DoTestConst.dll那么溜宽,會(huì)出現(xiàn)找不到dll之類的異常。這也充分說明了對(duì)于Readonly定義的變量是在運(yùn)行時(shí)加載的质帅。

動(dòng)態(tài)常量(Readonly)被賦值后不可以改變

ReadOnly 變量是運(yùn)行時(shí)變量适揉,它在運(yùn)行時(shí)第一次賦值后將不可以改變。其中“不可以改變”分為兩層意思:

對(duì)于值類型變量煤惩,值本身不可以改變(Readonly嫉嘀, 只讀)

對(duì)于引用類型變量,引用本身(相當(dāng)于指針)不可改變魄揉。

值類型變量剪侮,舉個(gè)例子說明一下:

publicclassStudent

{publicreadonlyintAge;publicStudent(intage)

{this.Age =age;

}

}

Student的實(shí)例Age在構(gòu)造函數(shù)中被賦值以后就不可以改變,下面的代碼不會(huì)編譯通過:

Student student =newStudent(20);

student.Age=21;//錯(cuò)誤信息:無法對(duì)只讀的字段賦值(構(gòu)造函數(shù)或變量初始化器中除外)

引用類型變量洛退,舉個(gè)例子說明一下:

publicclassStudent

{publicintAge;//注意這里的Age是沒有readonly修飾符的publicStudent(intage)

{this.Age =age;

}

}publicclassSchool

{publicreadonlyStudent Student;publicSchool(Student student)

{this.Student =student;

}

}

School實(shí)例的Student是一個(gè)引用類型的變量瓣俯,賦值后,變量不能再指向其他任何的Student實(shí)例兵怯,所以彩匕,下面的代碼將不會(huì)編譯通過:

School school =newSchool(newStudent(10));

school.Student=newStudent(20);//錯(cuò)誤信息:無法對(duì)只讀的字段賦值(構(gòu)造函數(shù)或變量初始化器中除外)

引用本身不可以改變,但是引用說指向的實(shí)例的值是可以改變的媒区。所以下面的代碼是可以編譯通過的:

School school =newSchool(newStudent(10));

school.Student.Age=20;

在構(gòu)造方法中驼仪,我們可以多次對(duì)Readonly修飾的常量賦值掸犬。舉個(gè)例子說明一下:

publicclassStudent

{publicreadonlyintAge =20;//注意:初始化器實(shí)際上是構(gòu)造方法的一部分,它其實(shí)是一個(gè)語法糖publicStudent(intage)

{this.Age =age;this.Age =25;this.Age =30;

}

}

總結(jié)

Const和Readonly的最大區(qū)別(除語法外)

Const的變量是嵌入在IL代碼中绪爸,編譯時(shí)就加載好登渣,不依賴外部dll(這也是為什么不能在構(gòu)造方法中賦值)。Const在程序集更新時(shí)容易產(chǎn)生版本不一致的情況毡泻。

Readonly的變量是在運(yùn)行時(shí)加載,需請(qǐng)求加載dll粘优,每次都獲取最新的值仇味。Readonly賦值引用類型以后,引用本身不可以改變雹顺,但是引用所指向的實(shí)例的值是可以改變的丹墨。在構(gòu)造方法中,我們可以多次對(duì)Readonly賦值嬉愧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贩挣,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子没酣,更是在濱河造成了極大的恐慌王财,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件裕便,死亡現(xiàn)場(chǎng)離奇詭異绒净,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)偿衰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門挂疆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人下翎,你說我怎么就攤上這事缤言。” “怎么了视事?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵胆萧,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我郑口,道長(zhǎng)鸳碧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任犬性,我火速辦了婚禮瞻离,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘乒裆。我一直安慰自己套利,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著肉迫,像睡著了一般验辞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上喊衫,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天跌造,我揣著相機(jī)與錄音,去河邊找鬼族购。 笑死壳贪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的寝杖。 我是一名探鬼主播违施,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼瑟幕!你這毒婦竟也來了磕蒲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤只盹,失蹤者是張志新(化名)和其女友劉穎辣往,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鹿霸,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡排吴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了懦鼠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钻哩。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖肛冶,靈堂內(nèi)的尸體忽然破棺而出街氢,到底是詐尸還是另有隱情,我是刑警寧澤睦袖,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布珊肃,位于F島的核電站,受9級(jí)特大地震影響馅笙,放射性物質(zhì)發(fā)生泄漏伦乔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一董习、第九天 我趴在偏房一處隱蔽的房頂上張望烈和。 院中可真熱鬧,春花似錦皿淋、人聲如沸招刹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽疯暑。三九已至训柴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間妇拯,已是汗流浹背幻馁。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留越锈,地道東北人宣赔。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像瞪浸,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子吏祸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 基本內(nèi)置類型 算術(shù)類型字符整型布爾值浮點(diǎn)數(shù) 空類型(void) 算術(shù)類型 帶符號(hào)類型和無符號(hào)類型int贡翘、short...
    2625K閱讀 3,183評(píng)論 0 1
  • 重點(diǎn)掌握 3 類對(duì)象和方法 對(duì)象就是一個(gè)物體 類的獨(dú)特存在就是一個(gè)實(shí)例蹈矮,對(duì)實(shí)例進(jìn)行操作叫做方法。方法可以應(yīng)用于類或...
    Coder大雄閱讀 1,258評(píng)論 0 2
  • 注:這是第三遍讀《C語言深度解剖》鸣驱,想想好像自從大學(xué)開始就沒讀完過幾本書泛鸟,其中譚浩強(qiáng)的那本《C語言程序設(shè)計(jì)(第四版...
    HavenXie閱讀 1,725評(píng)論 1 6
  • 作者 姜蘇 歐月琴乘38路公交車到木瀆翠坊橋那一站下車,然后步行一站路到梅雀路踊东。也就是臘梅弄旁邊的那條街北滥。到了的...
    姜蘇閱讀 224評(píng)論 0 0
  • 稻盛和夫在年輕的時(shí)候讀到了一本關(guān)于宗教的書,書中寫道闸翅,災(zāi)難和幸福都取決于人的內(nèi)心再芋,一個(gè)人擁有怎樣的內(nèi)心,就會(huì)創(chuàng)造怎...
    遇見明月閱讀 1,024評(píng)論 0 0