這是一個及其常見的問題網上已經有關於這個問題的很多討論但是我覺得都是不求甚解有一些還是在誤導別人下面我來說下我對這三者的理解如有錯誤的地方請大家及時指正
一與stringEmpty我認為是一樣的網上有一篇被轉載了幾十遍的文章是這樣說的stringEmpty 不分配存儲空間 分配一個長度為空的存儲空間我認為這句話是錯誤並且含糊不清的
實際上Empty是string類中的一個靜態的只讀字段他的定義是這樣的
public static readonly String Empty = ;
也就是說stringEmpty的內部實現是等於的
我要反駁stringEmpty 不分配存儲空間 分配一個長度為空的存儲空間這個觀點首先stringEmpty與都會分配存儲空間具體的說是都會在內存的棧和堆上分配存儲空間
有一點先說明一下引用類型是將對象是實際數據保存在堆上 將對象在堆上的地址保存在棧上因此stringEmpty與都會在棧上保存一個地址這個地址占字節指向內存堆中的某個長度為的空間這個空間保存的是stringEmpty的實際值這個我可以用VS跟蹤下內存給大家演示
上圖中的xe即是變量str在棧中存儲的地址
對於請看下圖
這個圖的效果跟上圖是一樣的也就是說也是在棧上保存了一個地址
CLR會對字符串進行優化所以和stringEmpty也都會被優化
聲明如下兩個變量
string str=;
string str=;
str與str的引用會是相同的也就是str與str在棧上保存的地址上相同的請看下圖
上圖是str的地址 上圖是str的地址
可見str於str的地址是相同的也就是說str會在堆上占用一個長度為的空間而str不會在堆上開辟新的空間 str於str在堆上共享同一空間
同理對於
string str=stringEmpty;
string str= stringEmpty;
str與str的地址也是相同的也是在內存堆上共享同一空間如下圖
上圖是str的地址 上圖是str的地址
如果非要說與stringEmpty有什麼不同的話我覺得是寫法不一樣stringEmpty看起來好看~!~是在優化方面稍有差別stringEmpty於c#對在語法級別的優化這點可以通過stringEmpty的內部實現看出來
public static readonly String Empty = ;
也就是說是通過CLR進行優化的CLR會維護一個字符串池以防在堆中創建重復的字符串而stringEmpty是一種c#語法級別的優化是在C#編譯器將代碼編譯為IL(即MSIL)時進行了優化即所有對string類的靜態字段Empty的訪問都會被指向同一引用以節省內存空間
所以對的優化更依賴CLR
給大家看一下二者編譯後的IL代碼:
string str=; 編譯後如下
ldstr //從字符串池中取出一個(實際上取的是地址)
stfld string ClassLibraryClass::str //將賦給str(實際上賦的是地址)
string str=stringEmpty; 編譯後如下
ldsfld string [mscorlib]SystemString::Empty//取得string類的靜態字段Empty(實際上取的是地址)
stfld string ClassLibraryClass::str//將Empty賦給str(實際上賦的是地址)
總結說了這麼一大推我自己都覺得羅嗦而且初學者朋友可能會看不懂本人語文學的不好表達能力一般還請大家諒解下面我會挑要害來說
與stringEmpty在用法與性能上基本沒區別stringEmpty是在語法級別對的優化
二stringEmpty與null的區別
因為stringEmpty與基本是一樣的所以stringEmpty與null的區別也就代表了與null的區別
那就是stringEmpty會在堆上占用一個長度為的空間而null不會具體內容如下
string str=;
string str=null;
如剛才所說str會在棧上保存一個地址這個地址占字節指向內存堆中的某個長度為的空間這個空間保存的是str的實際值
str同樣會在棧上保存一個地址這個地址也占字節但是這個地址是沒有明確指向的它哪也不指其內容為x如下圖
From:http://tw.wingwit.com/Article/program/net/201311/13583.html