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

值類型變量聲明后,不管是否已經賦值,編譯器為其分配內存。聲明一個引用類時,
只在棧中分配內存,用於存放地址,而並沒有為其分配堆上的內存空間。
值類型與引用類型使用區別:
本部分主要以自己編寫程序來體驗兩者區別。
對象的傳遞:

輸出結果:

將值類型的變量賦值給另一個變量,會執行一次賦值,賦值變量包含的值;
將引用類型的變量賦值給另一個引用類型變量,它復制的是引用對象的內存地址,在賦值后就會多個變量指向同一個引用對象實例。
參數按值傳遞:

輸出結果:

對於值類型(stu1),傳遞的是該值類型實例的一個副本,因此原本的值stu1並沒有改變;
對於引用類型(Student stu2),傳遞是變量stu2的引用地址(即stu2對象實例的內存地址)拷貝副本,因此他們操作都是同一個stu2對象實例。
參數按引用傳遞:

輸出結果:

不管是值類型還是引用類型,可以使用ref或out關鍵字來實現參數的按引用傳遞。ref或out關鍵字告訴編譯器,方法傳遞的是參數地址,而非參數本身。
在按引用傳遞時,方法的定義和調用都必須顯式的使用ref或out關鍵字,不可以省略,否則會引起編譯錯誤
注:string與一般引用類型有區別。以下是我對string與其他引用類型進行比較,發現的不同,所編寫的程序代碼
String:

顯示結果:

數組:

顯示結果:

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

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

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

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

裝箱和拆箱:
裝箱和拆箱是值類型和引用類型之間的相互轉換。
裝箱是值類型向引用類型轉換時發生的,拆箱是引用類型向值類型轉換時發生的。
裝箱是隱式的,拆箱是顯式的。如下圖代碼。

結果:

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

結果:

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

結果:

個人總結:
值類型有更好的效率,但不支持多態,適合用作存儲數據的載體。而引用類型支持多態,適合用於定義程序的行為。
引用類型可以派生新的類型,而值類型不能。
