關於值類型和引用類型方面的博客和文章可以說是汗牛充棟了,今天無意中又復讀了一下這方面的知識,感覺還是有許多新感悟的,就此時間分享一下:
CLR支持兩種類型:值類型和引用類型,看起來FCL的大多數類型是引用類型,但用的最多的還是值類型。引用類型總是從托管堆中分配,在用new操作符實例一個對象,返回對象內存地址存放在一個變量中。在使用引用類型時要了解其四個心理因素:
1.內存必須從托管堆中分配
2.堆上分配的每個對象都有一些額外成員,這些成員在使用前必須初始化。
3.對象中的其他字節總是設為零。
4.從托管堆分配對象時,可能強制執行一次垃圾回收。
由此可見,引用類型若是濫用勢必造成過載。再看值類型,其是輕量級類型,一般分配在線程棧上也可嵌入到引用類型對象中,承載它的變量不包含指向實例的指針,當然也不受垃圾回收器的控制,因此值類型的使用緩解了托管堆的壓力,減少了應用程序生存期內的垃圾回收的次數。
C#中稱為‘類’的都是引用類型,而值類型都成為結構或枚舉。所有結構都是由抽象類型System.ValueType直接派生。而其本身有直接從Object派生,所有枚舉從System.Enum抽象類型派生,Enum又從ValueType派生,環環相扣啊。
在設計自己的類型時,什麼時候將定義成值類型呢?
1.類型具有基元類型的行為(編譯器直接支持的數據類型(像Int32,Int64等))
2.類型不需要從其他任何類型繼承。
3.類型也不派生出其他任何類型。
4.由於值類型在作為實參或是返回值的時候,需要進行相應字段的復制,如若實例過大,會造成一定的性能損失。
所以要求類型實例較小(16字節以內),實例較大,但不作為方法實參傳遞和從方法返回也可。
--------------------------------------------------------------------------------------------------------------------------
關於值類型和引用類型的區別,大致列了一下幾點:
1.引用類型處於已裝箱形式,值類型處於未裝箱形式,兩者也可通過一定方式互相轉換(具體說明會在下一篇博客中詳談)
2.值類型不應引入任何新的虛方法,所有方法都不能是抽象的,且都是隱式密封防止重寫。
3.將值類型變量賦給另一個值類型變量,會執行逐字段復制。將引用類型的變量付給另一個引用類型,只復制內存地址。兩個或多個引用類型變量能引用堆上的同一個對象,對一個變量執行的操作可能影響到另一個變量引用的對象。相反,值類型變量獨立,不互相影響。
4.未裝箱的值類型不在堆上分配,所以該類型的一個實例一旦不在活動,為他們分配的存儲就會釋放,不會等待垃圾回收
大致就是這些內容,有時真的需要慢慢品味。。。