轉:String爲值類型仍是引用類型

 關於String爲值類型仍是引用類型的討論一直沒有平息,最近一直在研究性能方面的問題,今天再次將此問題進行一次明確。但願能給你們帶來點幫助,若是有錯誤請指出。html

 來看下面例子:數組

 //值類型
 int a = 1;
 int b = a;
 a = 2;
 Console.WriteLine("a is {0},b is {1}", a, b);性能

 //字符串
 String str1 = "ab";
 String str2 = str1;
 str1 = "abc";
 Console.WriteLine("str1 is {0},str2 is {1}", str1, str2);
 Console.Read();ui

 根據上面的例子:你以爲輸出結果應該是什麼?spa

 輸出結果:
 //a is 2,b is 1
 //str1 is abc,str2 is ab
 str2依然是ab,並無隨str1的改變而改變。指針

 若是String是引用類型,按理Str1和Str指針都指向同一內存地址,若是Str的內容發生改變,Str1應該也會相應變化。code

 此例子,看着String更像是值類型,可是MSDN卻說String是引用類型。orm

 引用類型包括:
 String
 全部數組(即便其元素是值類型)
 類類型(如Form)
 委託htm

 查看具體引用是否相同,若是Net可以查看內存地址就容易了,但不容許,只能經過間接方法來實現,看下面:對象

static void TestRefAddress()
{
    String str1 = "abc";
    String str2 = "abc";
    int a = 1;
    int b = 1;
    StringBuilder strb1 = new StringBuilder("abc");
    StringBuilder strb2 = new StringBuilder("abc");
    Console.WriteLine("Reference equal for string: " + Object.ReferenceEquals(str1, str2)); //結果true
    Console.WriteLine("Reference equal for int: " + Object.ReferenceEquals(a, b)); //結果false
    Console.WriteLine("Reference equal for StringBuilder: " + Object.ReferenceEquals(strb1, strb2)); //結果false
    Console.WriteLine("Value equal for string: " + str1.Equals(str2)); //結果true,相似於值類型
    Console.Read();
}

 結果爲什麼出現如此狀況,分析以下:

 Console.WriteLine("Reference equal for string: " + Object.ReferenceEquals(str1, str2)); //結果true,不一樣對象,但引用地址相同
 Console.WriteLine("Reference equal for int: " + Object.ReferenceEquals(a, b)); //結果false,值類型裝箱操做形成
 Console.WriteLine("Reference equal for StringBuilder: " + Object.ReferenceEquals(strb1, strb2)); //結果false,不一樣對象,引用地址不一樣
 Console.WriteLine("Value equal for string: " + str1.Equals(str2)); //結果true,相似於值類型

    由第一條結果,能夠斷定不一樣的String的,相同的值,其引用地址相同,再由第四條結果,str1.Equals(str2),二者結合,可得出結論,兩個String,若是賦值爲同一個值,在內存中只有一個字符串存在,兩個引用的地址相同。由此引出String的不變性。

    String的不變性:

    String最爲顯著的一個特色就是它具備恆定不變性。咱們一旦建立了一個String,在managed heap 上爲他分配了一塊連續的內存空間,咱們將不能以任何方式對這個String進行修改使之變長、變短、改變格式。全部對這個String進行各項操做(好比調用ToUpper得到大寫格式的String)而返回的String,實際上另外一個從新建立的String,其自己並不會產生任何變化。

    String 對象稱爲不可變的(只讀),由於一旦建立了該對象,就不能修改該對象的值。有的時候看來彷佛修改了,實際是String通過了特殊處理,每次改變值時都會創建一個新的String對象,變量會指向這個新的對象,而原來的仍是指向原來的對象,因此不會改變。這也是String效率低下的緣由。

    String的不變,並不是說String不能改變,而是其值不能改變。

    在例子中str1="ab",這時在內存中就將「ab」存下來,若是再建立字符串對象,其值也等於「ab」,str2="ab",則並不是再從新分配內存空間,而是將以前保存的「ab」的地址賦給str2的引用,這就能印證例子2中的結果。而當str1="abc"其值發生改變時,這時檢查內存,發現不存在此字符串,則從新分配內存空間,存儲「abc」,並將其地址賦給str1,而str2依然指向「ab」的地址,能夠印證例子1中的結果。

    結論:
    String是引用類型,只是編譯器對其作了特殊處理。

    轉載來源:https://www.cnblogs.com/littlewrong/p/9927154.html

相關文章
相關標籤/搜索