參考如下博文,我這裏只是筆記一下,原文會更加詳細html
堆棧和託管堆c#性能
值類型和引用類型spa
紅色表示——「這啥?」(真實1個問題引出3個問題)線程
CLR支持的兩種類型指針
引用類型:
引用類型從託管堆上分配,new操做符會返回對象的指針——指向對象數據的內存位置的一個引用,引用類型傳遞的是對象的指針(string特殊)。引用類型的變量都須要一次堆內存的分配。htm
值類型:對象
值類型通常在線程棧上分配,一個值類型變量包含了其實例的值,沒有引用指針。blog
相同點:繼承
都是System.Object的子類。
值類型也能夠繼承接口。
不一樣點:
一、 值類型分配在堆棧上,引用類型在託管堆上分配;
若是一個引用類型的某個屬性是值類型,這個值類型也分配在託管堆上。
二、 全部的值類型都是隱式密封的(sealed),不能繼承。
三、 值類型的賦值逐字段的複製,頻繁賦值也會形成性能上的壓力;引用類型的賦值只是指針傳遞。
四、 引用類型額外有類型對象指針和同步塊索引。
五、 值類型繼承自System.ValueType;引用類型繼承自System.Object,System.ValueType也繼承自System.Object。System.ValueType重寫了Equals和GetHashCode方法
性能:
值類型分配在棧上,在GC控制外,不會對GC形成壓力;
引用類型分配在堆中,會影響到GC,每一次到堆的內存分配都有可能進行一次垃圾收集操做。
裝箱拆箱:
裝箱是將值類型轉化爲引用類型,拆箱則是將引用類型轉化爲值類型。
裝箱:
一、 在託管堆中分配好了內存,分配的內存量爲值類型的各個字段須要的內存量加上託管上對象的兩個額外成員(類型對象指針,同步塊索引)須要的內存量
二、 值類型的字段複製到新分配的堆內存中。
三、 返回對象的地址,這個地址就是這個對象的引用。
拆箱:
一、 獲取已經裝箱的值類型實例的指針。
二、 把獲取到的值複製到棧。
(拆箱只能還原爲原先未裝箱以前的類型)
裝箱比較耗費性能,還可能引發GC操做