.NET Discovery 系列之二--string從入門到精通(勘誤版下)

作者: 緣清(aicken)  來源: 博客園  發布時間: 2010-01-13 16:04  閱讀: 1215 次  推薦: 0   原文鏈接   [收藏]  

系列文章導航:

.NET Discovery 系列之一--string從入門到精通(上)

.NET Discovery 系列之二--string從入門到精通(勘誤版下)

.NET Discovery 系列之三--深入理解.NET垃圾收集機制(上)

.NET Discovery 系列之四--深入理解.NET垃圾收集機制(下)

.Net Discovery 系列之五--Me JIT(上)

.NET Discovery 系列之六--Me JIT(下)

.NET Discovery 系列之七--深入理解.NET垃圾收集機制(拾貝篇)

 

  string可以說是.Net中比較復雜的一種數據類型,很多文章介紹過它,但不是很全面,本文全面的介紹了string的各種內部機制與特性,歡迎點評。本文為修正版,對前文進行了一些勘誤,感謝地獄門神、 Anytao、 eaglet 三位網友的幫助!

  前兩節我們介紹了string的兩個基本特性,如果你覺得你已經比較全面的了解了string,那么就來看看這第3、4兩節吧。

  三.有趣的比較操作

  在第一節與第二節中,我們分別介紹了字符串的恒定性與與駐留性,如果這位同學友覺得完全掌握了以上內容,那么就在第三節中檢驗一下自己的學習成果吧!

  以下10段簡單的代碼將通過值比較與地址引用比較,來說明前兩節講到的內容,大家也可以通過這些代碼來檢測一下自己對string的了解程度。

  代碼一:

 
string a = "str_1";
string b = "str_1";
Response.Write(a.Equals(b));
Response.Write(ReferenceEquals(a,b));


//輸出:True (Equals比較字符串對象的值)
//   True (ReferenceEquals比較字符串對象的引用,由于字符串駐留機制,
//a與b的引用相同)

  代碼二:

代碼
 
string a = "str_1str_2";
string b = "str_1";
string c = "str_2";
string d = b + c;
Response.Write(a.Equals(d));
Response.Write(ReferenceEquals(a, d));


//輸出:True(Equals比較字符串對象的值)
//False(ReferenceEquals比較字符串對象的引用,由于變量d的值為變量連接的結果,
//字符串駐留機制無效)

  代碼三:

代碼
 
string a = "str_1str_2";
string b = "str_1" + "str_2";
Response.Write(a.Equals(b));
Response.Write(ReferenceEquals(a, b));

//輸出:True(Equals比較字符串對象的值)
// True (ReferenceEquals比較字符串對象的引用,由于變量b的值為常量連接的結果,字符串駐留機制
有效。如果變量b的值由“常量+變量”的方式得出,則
 字符串駐留無效)

  代碼四:

 
string a = "str_1";
string b = String.Copy(a);
Response.Write(a.Equals(b));
Response.Write(ReferenceEquals(a, b));


//輸出:True(Equals比較字符串對象的值)
//False (ReferenceEquals比較字符串對象的引用,Copy操作產生了新的string對象)

  代碼五:

 
string a = "str_1";
string b = String.Copy(a);
b
= String.Intern(b);
Response.Write(a.Equals(b));
Response.Write(ReferenceEquals(a, b));

//輸出:True(Equals比較字符串對象的值)
//True (ReferenceEquals比較字符串對象的引用,String.Intern實現了字符串駐留)

  代碼六:

 
string a = "str_1";
string b = String.Copy(a);
string c = "str_1";
Response.Write((
object)a == (object)b);
Response.Write((
object)a == (object)c);
//輸出:False (“==”在兩邊為引用類型時,則比較引用的地址,所以a與b為不同引用)
True (ReferenceEquals比較字符串對象的引用,a與c由于字符串駐留機制,引用相同)

  代碼七:

 
string a = "str_1";
string c = "str_1";
Response.Write(a
== c);
//輸出:True

  剛才我們提到過,“==”在兩邊為引用類型時,則比較引用的地址;如果是值類型時則需要比較引用和值。string為引用類型,那么上面的代碼是比較了變量a與c的地址還是地址和值呢?答案是:比較了地址和值!因為在string類型比較的時候,“==”已經被重載為“Equals”了,所以,雖然你在用“==”比較兩個引用類型,但實際上是在用“Equals”比較它們的地址和值!(先比較地址,地址不等再比較值)

  代碼八:

 
string a = "a";
string b = new string('a', 1);
Response.Write(a.Equals(b));
Response.Write(ReferenceEquals(a, b));


//輸出:True (Equals比較值,a與b的值相同)
//False (ReferenceEquals比較字符串對象的引用)

  代碼九:

 
string a = "a";
string b = new string('a', 1);
Response.Write(a.Equals(
string.Intern(b)));
Response.Write(ReferenceEquals(a,
string.Intern(b)));
//輸出:True (Equals比較值,無論是否Intern都會相同)
// True (ReferenceEquals比較字符串對象的引用,Intern已經將b駐留至字符串池內)

  代碼十:

 
string a = "str";
string b = "str_2".Substring(0,3);
Response.Write(a.Equals(b));

//輸出:True (Equals比較值,a與c的值相同)
//False (ReferenceEquals比較字符串對象的引用,Substring操作產生了新的字符串對象)

  此段代碼產生了3個string對象,是哪3個呢?如果你不明白,還是從頭再看一遍吧!

 

  四.藝海拾貝

  這一節將主要給大家介紹一些string的常見問題。

  1.“string = ”與“new stirng()”的區別

 

 
string test = "a";
string test = new string('a', 1);

以上兩行代碼的效果是一樣的,它們的區別在于加載”a”的時間不同:第一行的“a”是一個常量,在編譯期就已經被放在一個叫做常量池的地方了,常量池通常裝載一些在編譯期被確定下來的數據,例如類、接口等等;而第二行是運行時CLR在堆中生成的值為“a”的字符串對象,所以后者沒有字符串駐留。

 

  2. string 與 String的區別

  String的大名叫做System.String,在編譯為IL代碼時,string和System.String會生成完全相同的代碼:(ps:long和System.Int64,float和System.Single等也有此特性)

 

 
string str_test = "test";
System.String Str_test
= "test";

IL碼:

 

 

 
// 代碼大小 14 (0xe)
.maxstack 1
.locals init ([0] string str_test,[1] string Str_test)
IL_0000: nop
IL_0001: ldstr "test"
IL_0006: stloc.0
IL_0007: ldstr "test"
IL_000c: stloc.1
IL_000d: ret

所以,二者的區別并不在于底層,而是在于string是類似于int的基元類型;System. String是框架類庫(FCL)的基本類型,二者之間有直接的對應關系。

 

  3.StringBuilder

  StringBuilder提供了高效創建字符串的方法,由StringBuilder表示的字符串是可變的(非恒定的),在需要多處使用“+”連接字符串變量的時候,推薦使用StringBuilder來完成,最后調用其ToString()方法輸出。當調用了StringBuilder的ToString()方法之后,StringBuilder將返回其內部維護的一個字符串字段引用,如再次修改StringBuilder,它將會創建一個新的字符串,這時被修改的是新的字符串,原來已經返回的字符串才不會發生改變。

  StringBuilder有兩個比較重要的內部字段,大家需要掌握:

  m_MaxCapacity:StringBuilder的最大容量,它規定了最多可以放置到m_StringValue的字符個數,默認值為Int32.MaxValue。m_MaxCapacity一旦被指定就不能再更改。

  m_StringValue:StringBuilder維護的一個字符數組串,實際上可以理解為一個字符串。StringBuilder重寫的Tostring()方法返回的就是這個字段。

  講到這里,你已經掌握了string的大部分秘密,怎么樣,你對string應該有全新的認識了吧!

0
0
 
標簽:string
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()