關於值類型和引用類型的區別


C#數據類型分為兩大類:值類型(數據存放在棧stack)和引用類型(數據存放在堆heap中,地址存放在棧stack)。下圖是列舉了兩種數據類型的數

值類型變量聲明后,不管是否已經賦值,編譯器為其分配內存。聲明一個引用類時,

只在棧中分配內存,用於存放地址,而並沒有為其分配堆上的內存空間。

 

值類型與引用類型使用區別:

本部分主要以自己編寫程序來體驗兩者區別。

對象的傳遞:

 輸出結果:

將值類型的變量賦值給另一個變量,會執行一次賦值,賦值變量包含的值;

將引用類型的變量賦值給另一個引用類型變量,它復制的是引用對象的內存地址,在賦值后就會多個變量指向同一個引用對象實例。

 參數按值傳遞:

輸出結果:

對於值類型(stu1),傳遞的是該值類型實例的一個副本,因此原本的值stu1並沒有改變;

對於引用類型(Student stu2),傳遞是變量stu2的引用地址(即stu2對象實例的內存地址)拷貝副本,因此他們操作都是同一個stu2對象實例。

參數按引用傳遞:

輸出結果:

不管是值類型還是引用類型,可以使用refout關鍵字來實現參數的按引用傳遞。refout關鍵字告訴編譯器,方法傳遞的是參數地址,而非參數本身。

在按引用傳遞時,方法的定義和調用都必須顯式的使用refout關鍵字,不可以省略,否則會引起編譯錯誤

注:string與一般引用類型有區別。以下是我對string與其他引用類型進行比較,發現的不同,所編寫的程序代碼

 String

顯示結果:

數組:

顯示結果:

結論

string字符串,一開始s1地址指向是hello world,因為s2=s1,所以s2地址也同樣指向hello world

s1再次賦值hello Yeebo時,堆中就會開辟出數據hello Yeebo,而且hello world沒有消失,沒有被覆蓋。s1地址就指向hello Yeebos2地址還是原來的hello world

在引用類型數組上,一開始s1s2的地址都指向{1,2,3}

當給S1進行數據更改時,由於是引用類型,所以在{123}上面進行更改,就會對S2進行覆蓋

裝箱和拆箱:

裝箱和拆箱是值類型和引用類型之間的相互轉換。

裝箱是值類型向引用類型轉換時發生的,拆箱是引用類型向值類型轉換時發生的。

裝箱是隱式的,拆箱是顯式的。如下圖代碼。

結果:

注:對於拆箱存在單詞或漢字等轉換為int的,這個過程是可能會報錯的, Convert.ToInt32()是不可行的,如下圖。

 

結果:

需要使用int.TryParse(),才不報錯,如下圖。

結果:

個人總結:

值類型有更好的效率,但不支持多態,適合用作存儲數據的載體。而引用類型支持多態,適合用於定義程序的行為。

引用類型可以派生新的類型,而值類型不能。

 


免責聲明!

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



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