原創|其它|編輯:郝浩|2009-07-29 14:36:07.000|閱讀 424 次
概述:本文介紹了一些String的特性。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
1.在DoNet中String是不可改變的,什么叫不可變呢,首先大家先看下面的例子:
string a = "1";Console.WriteLine(a);//1 a+="2";Console.WriteLine(a);//12大家可以看看下面生成的對應的IL代碼,可以看到a+="2"并非是在原有分配的堆中進行修改,而是創建了一個新的字符串;而+在IL中也是使用Concat,將兩個字符串聯;所以String的不可變就是當你在創建了字符串后其不可修改;.method private hidebysig static void Main(string[] args) cil managed{.entrypoint// 代碼大小 34 (0x22).maxstack 2.locals init ([0] string a)IL_0000: nopIL_0001: ldstr "1"IL_0006: stloc.0IL_0007: ldloc.0IL_0008: call void [mscorlib]System.Console::WriteLine(string)IL_000d: nopIL_000e: ldloc.0IL_000f: ldstr "2"IL_0014: call string [mscorlib]System.String::Concat(string,string)IL_0019: stloc.0IL_001a: ldloc.0IL_001b: call void [mscorlib]System.Console::WriteLine(string)IL_0020: nopIL_0021: ret} // end of method Program::Main
2.當創建多個字符串內容相同的對象時,都只會指向同一個引用;
string a = "11";string b = "11";string c = "11";string d = "1";d += "1";
a和b都指向同一個a的引用,并不會為b重新分配內存;這樣即可保證內存有效利用;這一點用IL不是很好看出來,所以大家可以按下面方法去比較他們的引用地址,都是指向同一個堆;
Console.WriteLine(string.ReferenceEquals(a, b));Console.WriteLine(string.ReferenceEquals(a, c));Console.WriteLine(string.ReferenceEquals(c, b));Console.WriteLine(string.ReferenceEquals(a, d));Console.WriteLine(string.ReferenceEquals(b, d));Console.WriteLine(string.ReferenceEquals(c, d));
運行結果:
TrueTrueTrueFalseFalseFalse
這說明當我們新建一個字符串以后,將為其分配內存,而之后如何有值和其相同的字符串不會被創建分配堆而是直接分配其引用;
3.字符串比較:
==和!=是為了比較String對象的值是否相同而不是比較引用;
例如等號首先是比較引用是否相同,因為引用相同值一定會相同,就避免了再去對值進行比較;
而引用如果不同再去比較值,相同則返回true;
總之==一定一定是為了比較字符串的值是否相同;
string s2 = new StringBuilder().Append("My").Append("Test").ToString();string s3 = new StringBuilder().Append("My").Append("Test").ToString();Console.WriteLine((object)s2==(object)s3);//False
上面是返回False,大家肯定有些迷惑,而此前一位園友則解釋我也不盡贊同,這里只發表我的解釋:
此處比較的是兩個引用類型,為什么這么說,因為大家都知道引用地址都是存放在棧中
,而此處正是將存放在棧中的引用地址裝箱轉換成了引用類型也就是分別創建了兩個值為引用地址的堆,而他們引用地址的值肯定不一樣,所以結果顯然就是False了;
4.為什么總是提倡使用StringBuilder對象;
如果用String,每進行一次字符串的拼接就要分配一個新的堆,如果只有一兩次倒無所謂,如果頻繁如此操作性能會很差;但StringBuilder是在為其分配的堆上做修改,不會重新分配,所以性能比String拼接字符串好;相信大家理解上面幾點了我這里也純粹是廢話了,呵呵!
5.最后就是看到有人提到Intern方法,我感覺他們對此方法具體功能理解不透徹存在誤解;
首先看下面例子:
static void Main(string[] args)
{
string a = "12";
string b = "1";
b += "2";
string c = string.Intern(b);
Console.WriteLine((object)a == (object)b);//false
Console.WriteLine((object)a == (object)c);//true
Console.WriteLine((object)b == (object)c);//false
}
static void Main(string[] args)
{
string a = "1212";
string b = "1";
b += "2";
string c = string.Intern(b);
Console.WriteLine((object)a == (object)b);//false
Console.WriteLine((object)a == (object)c);//false
Console.WriteLine((object)b == (object)c);//true
}
static void Main(string[] args)
{
string b = "1";
b += "2";
string c = string.Intern("12");
Console.WriteLine((object)b == (object)c);//false
}
先看第一個Main,我根據第一個Main來解釋:
如果傳遞給Intern的是一個變量的引用地址,那么他會檢索是否用與此引用地址所指向的堆的值相同的其他堆,如果有他會返回此堆的引用地址,也就是a。
我們再來看第二個Main來繼續解釋:
如果沒有找到與所指向的堆的值相同的其他堆,他將返回b的引用地址;
最后看第三個Main做最后解釋:
如果傳遞進去的是字符串而不是引用地址,他一樣會檢索是否存在與此字符串相同的堆,如果有則返回此堆的引用地址,如無則駐留此字符串并返回其引用地址;
而這里所將的駐留也是String的特殊之處,字符串在被創建后不會被立即回收,即使已不存在對其引用;他會在被創建之后一直駐留在內存中直至程序結束,大家可以查看MSDN解釋,下面將拿出一些MSDN的解釋來配合說明一下;
其中=>符號的是我做的注釋:
------MSDN解釋--Start------------------------------------------------------------------------------------
在1.1中
string str1 = String.Empty;
string str2 = String.Intern(String.Empty);
if ((object) str1) == ((object) str2);
...
==>是返回false,但在2.0中返回true,所以更加證實了如上所說;下面主要是講解了String的拘留池概念,大家理解上面概念后相信理解他也不成問題;
公共語言運行庫通過維護一個表來存放字符串,該表稱為拘留池,它包含程序中以編程方式聲明或創建的每個唯一的字符串的一個引用.因此,具有特定值的字符串的實例在系統中只有一個.例如,如果將同一字符串分配給幾個變量,運行庫就會從拘留池中檢索對該字符串的相同引用,并將它分配給各個變量.Intern 方法使用拘留池來搜索與 str 值相等的字符串.如果存在這樣的字符串,則返回拘留池中它的引用。
如果不存在,則向拘留池添加對 str 的引用,然后返回該引用.如果要減少應用程序分配的內存總量,請記住留用字符串有兩個不希望出現的副作用:首先,為留用的 String 對象分配的內存在公共語言運行庫 (CLR) 終止之前不大可能釋放.這是因為 CLR 對留用的 String 對象的引用可能保持到應用程序終止之后,甚至可能保持到應用程序域終止之后.其次,要留用字符串,必須先創建字符串.即使 String 對象使用的內存最終將通過垃圾回收,仍然必須分配該內存.
上面就說到了[為留用的 String 對象分配的內存在公共語言運行庫 (CLR) 終止之前不大可能釋放.]
.NET Framework 2.0 版引入了 CompilationRelaxations.NoStringInterning 枚舉成員.
NoStringInterning 成員將程序集標記為不需要字符串拘留.可以使用 CompilationRelaxationsAttribute 屬性將NoStringInterning 應用于某個程序集.使用本機映像生成器 (Ngen.exe) 將該程序集安裝到本地計算機上的本機映像緩存時,不使用字符串拘留.這里所提到的本機映像可以改善內存使用情況,大家可以查MSDN詳細了解;
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:IT專家網