.Net Discovery 系列之九–string從入門到精通(勘誤版下)

來源:互聯網
上載者:User

  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));
    Response.Write(ReferenceEquals(a, 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等也有此特性)
  C#代碼:
    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應該有全新的認識了吧!  

     我是李鳴(Aicken) 請您繼續關注我的下一篇文章。

 

“.Net Discovery 系列”是講解.Net平台本質的文章,現在已經有:

     .Net Discovery 系列之七--深入理解.Net垃圾收集機制(拾貝篇) 發布在新年第一秒

     .Net Discovery 系列之五--Me JIT(深入淺出.Net JIT 上)

     .Net Discovery 系列之六--Me JIT(深入淺出.Net JIT 下)

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

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

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

     .Net Discovery 系列之二--string從入門到精通(下)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.