偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

告訴一個(gè)不一樣的.NET Framework字符串駐留

開發(fā)
.NET Framework字符串駐留的機(jī)制實(shí)際上并沒有我們想象的那么簡(jiǎn)單。下面我們就來(lái)通過(guò)一段代碼的解讀,來(lái)詳細(xì)分析這一機(jī)制的相關(guān)概念。

.NET Framework在實(shí)際應(yīng)用中,還是相當(dāng)復(fù)雜的。我們要向熟練的運(yùn)用這一架構(gòu)來(lái)服務(wù)于我們的程序代碼中。關(guān)于.NET Framework字符串駐留的機(jī)制,對(duì)于那些了解它的人肯定會(huì)認(rèn)為很簡(jiǎn)單,但是我相信會(huì)有很大一部分人對(duì)它存在迷惑。在開始關(guān)于字符串的駐留之前,先給出一個(gè)有趣的Sample: #t#

Code Snip:

  1. static void Main(string[] args)   
  2. {   
  3. string str1 = "ABCD1234";   
  4. string str2 = "ABCD1234";  
  5. string str3 = "ABCD";   
  6. string str4 = "1234";   
  7. string str5 = "ABCD" + "1234";   
  8. string str6 = "ABCD" + str4;   
  9. string str7 = str3 + str4;   
  10. Console.WriteLine("string str1 = 
    \"ABCD1234\";");  
  11. Console.WriteLine("string str2 = 
    \"ABCD1234\";"); 
  12. Console.WriteLine("string str3 = 
    \"ABCD\";"); 
  13. Console.WriteLine("string str4 = 
    \"1234\";"); 
  14. Console.WriteLine("string str5 = 
    \"ABCD\" + \"1234\";"); 
  15. Console.WriteLine("string str6 = 
    \"ABCD\" + str4;"); 
  16. Console.WriteLine("string str7 = 
    str3 + str4;"); 
  17. Console.WriteLine("\nobject.Reference
    Equals(str1, str2) = {0}", object.
    ReferenceEquals(str1, str2)); 
  18. Console.WriteLine("object.ReferenceEquals
    (str1, \"ABCD1234\") = {0}", object.
    ReferenceEquals(str1, "ABCD1234"));   
  19. Console.WriteLine("\nobject.Reference
    Equals(str1, str5) = {0}", object.
    ReferenceEquals(str1, str5)); 
  20. Console.WriteLine("object.Reference
    Equals(str1, str6) = {0}", object.
    ReferenceEquals(str1, str6)); 
  21. Console.WriteLine("object.ReferenceEquals
    (str1, str7) = {0}", object.ReferenceEquals
    (str1, str7)); 
  22. Console.WriteLine("\nobject.ReferenceEquals
    (str1, string.Intern(str6)) = {0}", object.
    ReferenceEquals(str1, string.Intern(str6)));   
  23. Console.WriteLine("object.ReferenceEquals
    (str1, string.Intern(str7)) = {0}", object.
    ReferenceEquals(str1, string.Intern(str7)));   

接下來(lái)我們來(lái)逐句地分析這段.NET Framework字符串駐留代碼:

首先我們創(chuàng)建了兩個(gè)完全相同的字符串(ABCD1234),并將他們分別賦予了兩個(gè)字符創(chuàng)變量——str1和str2。然后把它們傳給了object.ReferenceEquals。我們知道object.ReferenceEquals是用于確定兩個(gè)變量是否具有相同的引用——換句話說(shuō),當(dāng)兩個(gè)變量引用的是同一塊托管推的內(nèi)存快的時(shí)候,返回True,否則返回False。

令我們感到奇怪的是,當(dāng)我們分別創(chuàng)建的引用類型兩個(gè)變量——string是引用類型。照理說(shuō)CLR會(huì)在托管堆(Managed Heap)中為它們分配兩段內(nèi)存快,他們不可能具有相同的引用才對(duì),但是為什么object.ReferenceEquals 方法會(huì)返回True呢。而對(duì)于第二個(gè)比較——一個(gè)字符串變量和一個(gè)和他具有相同內(nèi)容的字符串("ABCD1234";)直接進(jìn)行比較,按照我們對(duì)CLR內(nèi)存的分配的一般理解,應(yīng)該是CLR首先會(huì)在托管堆中為這段字符串("ABCD1234")分配內(nèi)存快,然后把相對(duì)應(yīng)的引用傳遞給 object.ReferenceEquals方法(由于分配在托管堆的這段字符串并沒有被任何變量引用,所以當(dāng)垃圾回收的時(shí)候會(huì)被回收掉),所以無(wú)論如何也不應(yīng)該返回True。

我們先把問題留到最后,接著分析我們的Sample。上面?zhèn)儗?duì)字符串變量之間以及變量與字符串之間進(jìn)行了比較,如果我們對(duì)一個(gè)字符串變量和一個(gè)動(dòng)態(tài)創(chuàng)建的字符串(通過(guò)+Operator把兩個(gè)字符串連接起來(lái))進(jìn)行比較,結(jié)果又會(huì)如何呢?我們來(lái)看看下面的偽代碼演示:

在上面的.NET Framework字符串駐留例子中,我們用三種不同的方式創(chuàng)建了3 個(gè)字符串變量(str5,str6,str7)——string+string;string+variable;variable+variable。然后分別和我們已經(jīng)創(chuàng)建的、和它們具有相同字符串“值”的變量(str1)作比較。同樣令我們感到奇怪的是第一個(gè)返回True,而后兩個(gè)則為False。帶著這些疑惑我們來(lái)看看對(duì)于string這一特殊的類型說(shuō)采用的特殊的使用機(jī)制。

1. System.String雖然是一個(gè)引用類型,但是它具有其自身的特殊性。我們最容易想到的是它創(chuàng)建的特殊性——一般的對(duì)象在創(chuàng)建的時(shí)候需要通過(guò)new關(guān)鍵字調(diào)用對(duì)應(yīng)的構(gòu)造函數(shù)來(lái)實(shí)現(xiàn);而創(chuàng)建一段string不需要這么做——我們只需要把對(duì)應(yīng)的字符換賦給給對(duì)應(yīng)的字符串變量就可以了。

之所以存在著這種差異,是因?yàn)樗麄冊(cè)趧?chuàng)建過(guò)程中使用的IL指令時(shí)不同的——一般的引用對(duì)象的創(chuàng)建是通過(guò)newobj這樣一個(gè)IL指令來(lái)實(shí)現(xiàn)的,而創(chuàng)建一個(gè)字符串變量的IL指令則是ldstr (load string)。(象C#,VB.NET這樣的語(yǔ)言畢竟是高級(jí)語(yǔ)言,進(jìn)行了高度的抽象,站在這樣的角度分析問題往往不能夠看到其實(shí)質(zhì),所以有時(shí)候我們把應(yīng)該從交底層上面找突破口——比如分析IL,Metadata…);

2.由于String是我們做到頻率最高的一種類型,CLR考慮性能的提升和內(nèi)存節(jié)約上,對(duì)于相同的字符串,一般不會(huì)為他們分別分配內(nèi)存塊,相反地,他們會(huì)共享一塊內(nèi)存。CLR實(shí)際上采用這個(gè)的機(jī)制來(lái)實(shí)現(xiàn)的:CLR內(nèi)部維護(hù)著一塊特殊的數(shù)據(jù)結(jié)構(gòu)——我們可以把它看成是一個(gè)Hash table,這個(gè)Hash table維護(hù)者大部分創(chuàng)建的string(我這里沒有說(shuō)全部,因?yàn)橛刑乩?。這個(gè)Hash table的Key對(duì)應(yīng)的相應(yīng)的string本身,而Value則是分配給這個(gè)string的內(nèi)存塊的引用。

當(dāng)CLR初始化的時(shí)候創(chuàng)建這個(gè)Hash table。一般地,在程序運(yùn)行過(guò)程中,如果需要的創(chuàng)建一個(gè)string,CLR會(huì)根據(jù)這個(gè)string的Hash Code試著在Hash table中找這個(gè)相同的string,如果找到,則直接把找到的string的地址賦給相應(yīng)的變量,如果沒有則在托管堆中創(chuàng)建一個(gè)string,CLR 會(huì)先在managed heap中創(chuàng)建該strng,并在Hash table中創(chuàng)建一個(gè)Key-Value Pair——Key為這個(gè)string本身,Value位這個(gè)新創(chuàng)建的string的內(nèi)存地址,這個(gè)地址最重被賦給響應(yīng)的變量。這樣我們就能解釋上面.NET Framework字符串駐留的疑問了。

當(dāng)創(chuàng)建str1的時(shí)候,CLR現(xiàn)在我們上面提到的Hash table中找“ABCD1234”這樣的一個(gè)string,沒有找到,則在托管堆中為這個(gè)string分配一塊內(nèi)存,然后在Hash table為該string添加一個(gè)Key-Value Pair。接著創(chuàng)建str2,CLR仍然會(huì)在Hash table找ABCD1234這樣的一個(gè)string,這回它會(huì)找到我們新創(chuàng)建的這個(gè)Entry,所以這個(gè)Key-Value Pair中Value(string的地址)會(huì)賦給str2。因?yàn)閟tr1和str2 具有相同的引用,所以調(diào)用object.ReferenceEquals返回True。同理當(dāng)我們對(duì)str1和"ABCD1234"進(jìn)行比較的時(shí)候, str1直接傳入該方法,放傳入"ABCD1234"這個(gè)字符串的時(shí)候,CLR同樣會(huì)在Hash table找ABCD1234這樣的一個(gè)string,相同的Entry被找到,這個(gè)Entry(Key-Value Pair)的Value(string的地址)被傳到object.ReferenceEquals,所以他們?nèi)匀幌嗤囊茫Y(jié)果返回True。

3.并非所有的情況下.NET Framework字符串駐留都會(huì)起作用。對(duì)于對(duì)一個(gè)動(dòng)態(tài)創(chuàng)建的字符串(比如string+variable;variable+variable),這種駐留機(jī)制便不會(huì)起作用。因?yàn)閷?duì)于這樣的字符串,是不會(huì)被添加到內(nèi)部的Hash table中的。但是對(duì)于string+string則不同,因?yàn)楫?dāng)這樣的語(yǔ)句被編譯成IL的時(shí)候,編譯器是先把結(jié)構(gòu)計(jì)算出來(lái),然后再調(diào)用ldstr指令 ——而對(duì)于string+variable;variable+variable這種情況,所對(duì)應(yīng)的IL指令是Concat。所以對(duì)于string+ string字符串的駐留仍然有效。

所以現(xiàn)在我們就可以解釋第二個(gè)疑問了。

雖然對(duì)于對(duì)一個(gè)動(dòng)態(tài)創(chuàng)建的字符串(比如 string+variable;variable+variable),.NET Framework字符串駐留機(jī)制便不會(huì)起作用。但是我們可以手工的啟用駐留機(jī)制——那就是調(diào)用定義的 System.String中的靜態(tài)方法Intern。這個(gè)方法接受一個(gè)字符串作為他的輸入?yún)?shù),返回的經(jīng)過(guò)駐留處理的string。他的實(shí)現(xiàn)機(jī)制是:如果能在內(nèi)部的Hash Table中找到傳入的string,則返回對(duì)應(yīng)的string引用,否則就在Hash Table添加該string對(duì)應(yīng)的Entry,并返回string的引用。所以下面的代碼就不難解釋了。

責(zé)任編輯:曹凱 來(lái)源: IT168
相關(guān)推薦

2012-03-07 17:24:10

戴爾咨詢

2012-12-20 10:17:32

IT運(yùn)維

2009-07-07 10:44:14

多態(tài)

2021-10-20 20:02:47

字符變量函數(shù)

2020-05-06 15:18:37

戴爾

2016-05-09 18:40:26

VIP客戶緝拿

2015-10-19 12:33:01

華三/新IT

2017-05-25 15:02:46

聯(lián)宇益通SD-WAN

2012-12-21 10:42:49

數(shù)據(jù)分析中土世界數(shù)據(jù)可視化項(xiàng)目

2009-02-04 15:43:45

敏捷開發(fā)PHPFleaPHP

2009-12-01 16:42:27

Gentoo Linu

2018-05-09 15:42:24

新零售

2009-06-12 15:26:02

2011-02-28 10:38:13

Windows 8

2016-03-24 18:51:40

2013-01-11 18:10:56

軟件

2015-08-25 09:52:36

云計(jì)算云計(jì)算產(chǎn)業(yè)云計(jì)算政策

2010-12-07 09:37:20

數(shù)據(jù)中心

2015-08-04 14:49:54

Discover

2011-03-14 16:51:24

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)