C#參考型別和實值型別的區別

來源:互聯網
上載者:User
C#參考型別和實值型別的區別

    我們都知道,c#的兩大資料類型分別為實值型別和參考型別。很多人或許閉著眼睛都能說出實值型別包括簡單類型、結構體類型和枚舉類型,參考型別包括自訂類、數組、介面、委託等,但是當被問及到二者之間的聯絡和區別,什麼時候用struct什麼時候用class時,就常常混淆不清了。為此,瞭解實值型別和參考型別的本質差異就變的很有必要了。

  1. 實值型別直接儲存其值,變數本身就包含了其執行個體資料,而參考型別儲存的只是執行個體資料的記憶體引用。因此,一個實值型別變數就永遠不會影響到其他的實值型別變數,而兩個參考型別變數則很有可能指向同一地址,從而發生相互影響。
  2. 從記憶體配置上來看,實值型別通常分配線上程的堆棧上,範圍結束時,所佔空間自行釋放,效率高,無需進行地址轉換,而參考型別通常分配在託管堆上,由GC來控制其回收,需要進行地址轉換,效率降低,這也正是c#需要定義兩種資料類型的原因之一。
  3. 實值型別均隱式派生自System.ValueType,而System.ValueType又直接派生於System.Object,每種實值型別均有一個隱式的預設建構函式來初始化該類型的預設值,注意所有的實值型別都是密封(sealed)的,所以無法派生出新的實值型別。而且System.ValueType本身是一個類類型,而不是實值型別,因為它重寫了object的Equals()方法,所以對實值型別將按照執行個體的值來比較,而不是比較引用地址。
  4. C# 的統一類型系統,使得實值型別可以轉化為對象來處理,這就是常說的裝箱和拆箱。由於裝拆箱需要裝建全新對象或做強制類型轉換,這些操作所需時間和運算要遠遠大於賦值操作,因此不提倡使用它,同時也要盡量避免隱式裝拆箱的發生。

註:棧是作業系統分配的一個連續的記憶體地區,用於快速存取資料。因為實值型別的容量是已知的,因此它可儲存在棧上。而託管堆是CLR在應用程式啟動時為應用程式預留的一塊連續記憶體區,是用於動態記憶體分配的記憶體區,參考型別的容量只有到運行時才能確定,所有用堆來儲存參考型別。

 

 

C#的兩種資料類型延伸之一--巢狀型別的記憶體配置

    對於參考型別嵌套實值型別,以及實值型別嵌套參考型別的情況下,記憶體配置可以根據以下兩條規律來判斷:

•     參考型別始終部署在託管堆上;

•     實值型別總是分配在它聲明的地方:作為欄位時,跟隨其所屬的Object Storage Service;作為局部變數時,儲存在棧上。

 

 

C#的兩種資料類型延伸之二--string類型

    string是一個很有意思的參考型別,為什麼說它很有意思呢?因為它表現了很多實值型別的特點。請看一下程式碼範例:

樣本1

string str1 = "abc";

string str2 = str1;

str1 = "123";

Console.WriteLine(str2);

樣本2(msdn上的例子)

string a = "hello";

string b = "h";

// Append to contents of 'b'

b += "ello";

Console.WriteLine(a == b);

樣本1的輸出結果是abc,改變str1的值對str2沒有影響。

樣本2的輸出結果是True。

    這樣的結果會使我們誤以為string就是實值型別。其實不然,樣本1中str1 = "123"語句編譯器私底下建立了一個新的字串對象來儲存新的字元序列"123",也就是此str1已非彼str1了,“此”str1的值的改變也就不能影響“彼”str1的值了,當然str2的值也就不會改變了。實質上str1 = "123"是str1=new string("123")的簡寫,它的每一次賦值都會拋掉原來的對象而產生一個新的字串對象,分配新的記憶體空間,因此string是不可改變的。如果要建立可修改的字串,可使用stringbuilder以獲得更好的效能。至於樣本2是因為為了方便比較字串的值重定義了string的運算子==!=

 

 

C#的兩種資料類型延伸之三--struct和class 

    class和struct的文法基本相同,從聲明到使用,都很相似。但是struct的約束要比class多,理論上,struct能做到的class都能做到,但class能做到的stuct卻不一定做的到,也就是說struct都能被class所代替。那麼為什麼還要使用struct呢?存在即是合理的,struct在很多方面有著效能優勢。讓我們看看它們的主要區別在哪裡?

  • 資料類型不一樣,struct是實值型別,class是參考型別,因此它們具有所有實值型別和參考型別之間的差異。由於堆棧的執行效率要比堆的執行效率高,但是堆棧資源卻很有限,不適合處理邏輯複雜的大對象,因此struct常用來處理作為基底類型對待的小對象,而class來處理某個商業邏輯。
  • 從繼承性來看,struct既不能繼承也不能被繼承,但是可以實現介面,而Class就可以完全擴充了。
  • 內部結構有區別,struct只能添加帶參的建構函式,不能使用abstract和protected等修飾符,不能初始化執行個體欄位,但是值得注意的是,struct可以重寫System.Object的3個虛方法,Equals()、ToString()和GetHashTable(),Class沒有這些限制。

比較struct和class的不同,可以得出以下幾條struct和class的使用原則:

1 在表示諸如點、矩形等主要用來儲存資料的輕量級對象時,首選struct。

2 在表示資料量大、邏輯複雜的大對象時,首選class。

3 在表現抽象和多層級的對象層次時,class是最佳選擇

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.