C#中string.Empty和null的區(qū)別詳解
這是一個(gè)及其常見(jiàn)的問(wèn)題,網(wǎng)上已經(jīng)有關(guān)于這個(gè)問(wèn)題的很多討論。但是我覺(jué)得都是不求甚解,有一些還是在誤導(dǎo)別人。下面我來(lái)說(shuō)下我對(duì)這三者的理解,如有錯(cuò)誤的地方請(qǐng)大家及時(shí)指正。
一:""與string.Empty我認(rèn)為是一樣的。網(wǎng)上有一篇被轉(zhuǎn)載了幾十遍的文章是這樣說(shuō)的string.Empty 不分配存儲(chǔ)空間,"" 分配一個(gè)長(zhǎng)度為空的存儲(chǔ)空間,我認(rèn)為這句話是錯(cuò)誤并且含糊不清的。
1、實(shí)際上Empty是string類(lèi)中的一個(gè)靜態(tài)的只讀字段,他的定義是這樣的:
public static readonly String Empty = "";
也就是說(shuō)string.Empty的內(nèi)部實(shí)現(xiàn)是等于””的。
2、我要反駁string.Empty 不分配存儲(chǔ)空間,"" 分配一個(gè)長(zhǎng)度為空的存儲(chǔ)空間這個(gè)觀點(diǎn)。首先string.Empty與""都會(huì)分配存儲(chǔ)空間,具體的說(shuō)是都會(huì)在內(nèi)存的棧和堆上分配存儲(chǔ)空間。
有一點(diǎn)先說(shuō)明一下,引用類(lèi)型是將對(duì)象是實(shí)際數(shù)據(jù)保存在堆上, 將對(duì)象在堆上的地址保存在棧上。因此string.Empty與””都會(huì)在棧上保存一個(gè)地址這個(gè)地址占4字節(jié),指向內(nèi)存堆中的某個(gè)長(zhǎng)度為0的空間,這個(gè)空 間保存的是string.Empty的實(shí)際值。這個(gè)我可以用VS2010跟蹤下內(nèi)存給大家演示。
上圖中的0x01e81228即是變量str在棧中存儲(chǔ)的地址。
對(duì)于"",請(qǐng)看下圖
這個(gè)圖的效果跟上圖是一樣的,也就是說(shuō)””也是在棧上保存了一個(gè)地址。
3、CLR會(huì)對(duì)字符串進(jìn)行優(yōu)化,所以””和string.Empty也都會(huì)被優(yōu)化。
聲明如下兩個(gè)變量
string str1=””;
string str2=””;
str1與str2的引用會(huì)是相同的也就是str1與str2在棧上保存的地址上相同的。請(qǐng)看下圖
上圖是str1的地址。
上圖是str2的地址
4、如果非要說(shuō)””與string.Empty有什么不同的話,我覺(jué)得1是寫(xiě)法不一樣,string.Empty看起來(lái)好看~!~。2是在優(yōu)化 方面稍有差別。string.Empty于c#對(duì)””在語(yǔ)法級(jí)別的優(yōu)化。這點(diǎn)可以通過(guò)string.Empty的內(nèi)部實(shí)現(xiàn)看出來(lái)。
public static readonly String Empty = "";
也就是說(shuō)””是通過(guò)CLR進(jìn)行優(yōu)化的,CLR會(huì)維護(hù)一個(gè)字符串池,以防在堆中創(chuàng)建重復(fù)的字符串。而string.Empty是一種c#語(yǔ)法級(jí)別 的優(yōu)化,是在C#編譯器將代碼編譯為IL(即MSIL)時(shí)進(jìn)行了優(yōu)化,即所有對(duì)string類(lèi)的靜態(tài)字段Empty的訪問(wèn)都會(huì)被指向同一引用,以節(jié)省內(nèi)存 空間。
所以對(duì)””的優(yōu)化更依賴CLR。
給大家看一下二者編譯后的IL代碼:
string str1=””; 編譯后如下:
ldstr "" //從字符串池中取出一個(gè)””(實(shí)際上取的是地址)
stfld string ClassLibrary1.Class1::str1 //將””賦給str1(實(shí)際上賦的是地址)
string str2=string.Empty; 編譯后如下:
ldsfld string [mscorlib]System.String::Empty//取得string類(lèi)的靜態(tài)字段Empty(實(shí)際上取的是地址)
stfld string ClassLibrary1.Class1::str2//將Empty賦給str2(實(shí)際上賦的是地址)
總結(jié):說(shuō)了這么一大推我自己都覺(jué)得羅嗦,而且初學(xué)者朋友可能會(huì)看不懂。本人語(yǔ)文學(xué)的不好,表達(dá)能力一般還請(qǐng)大家諒解,下面我會(huì)挑要害來(lái)說(shuō)。
“”與string.Empty在用法與性能上基本沒(méi)區(qū)別。string.Empty是在語(yǔ)法級(jí)別對(duì)””的優(yōu)化。
二、string.Empty與null的區(qū)別
因?yàn)閟tring.Empty與””基本是一樣的,所以string.Empty與null的區(qū)別也就代表了””與null的區(qū)別。
1、 那就是string.Empty會(huì)在堆上占用一個(gè)長(zhǎng)度為0的空間,而null不會(huì)。具體內(nèi)容如下:
string str1=””;
string str2=null;
如剛才所說(shuō)str1會(huì)在棧上保存一個(gè)地址,這個(gè)地址占4字節(jié),指向內(nèi)存堆中的某個(gè)長(zhǎng)度為0的空間,這個(gè)空間保存的是str1的實(shí)際值。
str2同樣會(huì)在棧上保存一個(gè)地址,這個(gè)地址也占4字節(jié),但是這個(gè)地址是沒(méi)有明確指向的,它哪也不指,其內(nèi)容為0x00000000。如下圖
相關(guān)文章
C#中單問(wèn)號(hào)(?)和雙問(wèn)號(hào)(??)的用法整理
本文詳細(xì)講解了C#中單問(wèn)號(hào)(?)和雙問(wèn)號(hào)(??)的用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05C# Xamarin利用ZXing.Net.Mobile進(jìn)行掃碼的方法
這篇文章主要介紹了C# Xamarin利用ZXing.Net.Mobile進(jìn)行掃碼的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06c#實(shí)現(xiàn)把異常寫(xiě)入日志示例(異常日志)
這篇文章主要介紹了c#實(shí)現(xiàn)把異常寫(xiě)入日志示例(異常日志),需要的朋友可以參考下2014-04-04C#應(yīng)用BindingSource實(shí)現(xiàn)數(shù)據(jù)同步的方法
這篇文章主要介紹了C#應(yīng)用BindingSource實(shí)現(xiàn)數(shù)據(jù)同步的方法,需要的朋友可以參考下2014-08-08asp.net core mvc權(quán)限控制:在視圖中控制操作權(quán)限
本文主要介紹了asp.net core mvc權(quán)限控制:在視圖中控制操作權(quán)限。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02C#實(shí)現(xiàn)給定字符串生成MD5哈希的方法
這篇文章主要介紹了C#實(shí)現(xiàn)給定字符串生成MD5哈希的方法,涉及C#操作字符串的相關(guān)技巧,需要的朋友可以參考下2015-06-06