參考以下博文,我這裡只是筆記一下,原文會更加詳細 c#基礎系列1 深入理解值類型和引用類型 堆棧和托管堆c# 值類型和引用類型 紅色表示——“這啥?”(真實1個問題引出3個問題) CLR支持的兩種類型 引用類型: 引用類型從托管堆上分配,new操作符會返回對象的指針——指向對象數據的記憶體位置的一個引 ...
參考以下博文,我這裡只是筆記一下,原文會更加詳細
值類型和引用類型
紅色表示——“這啥?”(真實1個問題引出3個問題)
CLR支持的兩種類型
引用類型:
引用類型從托管堆上分配,new操作符會返回對象的指針——指向對象數據的記憶體位置的一個引用,引用類型傳遞的是對象的指針(string特殊)。引用類型的變數都需要一次堆記憶體的分配。
值類型:
值類型一般在線程棧上分配,一個值類型變數包含了其實例的值,沒有引用指針。
相同點:
都是System.Object的子類。
值類型也可以繼承介面。
不同點:
1、 值類型分配在堆棧上,引用類型在托管堆上分配;
如果一個引用類型的某個屬性是值類型,這個值類型也分配在托管堆上。
2、 所有的值類型都是隱式密封的(sealed),不能繼承。
3、 值類型的賦值逐欄位的複製,頻繁賦值也會造成性能上的壓力;引用類型的賦值只是指針傳遞。
4、 引用類型額外有類型對象指針和同步塊索引。
5、 值類型繼承自System.ValueType;引用類型繼承自System.Object,System.ValueType也繼承自System.Object。System.ValueType重寫了Equals和GetHashCode方法
性能:
值類型分配在棧上,在GC控制外,不會對GC造成壓力;
引用類型分配在堆中,會影響到GC,每一次到堆的記憶體分配都有可能進行一次垃圾收集操作。
裝箱拆箱:
裝箱是將值類型轉化為引用類型,拆箱則是將引用類型轉化為值類型。
裝箱:
1、 在托管堆中分配好了記憶體,分配的記憶體量為值類型的各個欄位需要的記憶體量加上托管上對象的兩個額外成員(類型對象指針,同步塊索引)需要的記憶體量
2、 值類型的欄位複製到新分配的堆記憶體中。
3、 返回對象的地址,這個地址就是這個對象的引用。
拆箱:
1、 獲取已經裝箱的值類型實例的指針。
2、 把獲取到的值複製到棧。
(拆箱只能還原為原先未裝箱之前的類型)
裝箱比較耗費性能,還可能引起GC操作