String為值類型還是引用類型


關於String為值類型還是引用類型的討論一直沒有平息,最近一直在研究性能方面的問題,今天再次將此問題進行一次明確。希望能給大家帶來點幫助。 如果有錯誤請指出。

來看下面例子:

復制代碼
復制代碼
//值類型
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();
復制代碼
復制代碼

根據上面的例子:你覺得輸出結果應該是什么?

 

輸出結果:

//結果:
//a is 2,b is 1
//str1 is abc,str2 is ab
str2依然是ab,並沒有隨str1的改變而改變。

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

此例子,看着string更像是值類型。

但是MSDN卻說String是引用類型,

引用類型包括:
String

所有數組,即使其元素是值類型

類類型,如 Form

委托

查看具體引用是否相同

如果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/peterpan0707007/p/6531194.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM