第5章 基元型別 引用型別與值型別 (2)

2022-03-25 07:19:17 字數 1731 閱讀 5299

所有的值型別都繼承自system.valuetype,而system.valuetype繼承自system.object。它重寫了system.object中的equals方法和gethashcode方法。當定義自己的值型別時我們也應重寫equals方法和gethashcode方法,為它們提供乙個顯式的實現

定義值型別時不能為其選擇任何的基型別,但可以作為乙個或多個介面的實現。此外clr不允許乙個值型別被作為其他任何引用型別或值型別的基類

如果型別滿足以下這些條件,我們就應該考慮將其宣告為值型別:

1、該型別的行為類似於基元型別

2、該型別不需要繼承自任何其他型別也不會被任何其他型別繼承

3、該型別的例項不會頻繁地用於方法的引數傳遞。因為預設情況下引數以傳值的方式傳遞,會導致值型別例項中的字段被拷貝,損傷應用程式效能。同樣該型別的例項也不應被作為方法的結果頻繁的返回(引用型別的例項作為引數傳值時為什麼效能損失較小?)

4、該型別的例項不會被頻繁的用於諸如arraylist、hashtable之類的集合中。因為這些管理一組通用物件集合的類會對值型別例項執行裝箱操作

我們不應向值型別中引入任何新的虛方法(實際上這樣做在c#中是非法的),更不可以有任何的抽象方法,所有方法都隱含為sealed

未裝箱的值型別因為沒有分配在託管堆上,所以一旦定義其實例的方法不再處於活動狀態,為例項分配的空間就會立即釋放

clr如何控制型別中字段的布局

為提高效能,clr會對型別例項中的字段按一定方式排序,例如clr可能會在記憶體中重新排列物件的字段,以使物件引用可以聚合在一起,並能恰當的對齊和包裝資料字段。

system.runtime.interopservices.structlayoutattribute特性可以告訴clr我們期望的排序方式,傳入layoutkind.auto表示讓clr自己排列字段,傳入layoutkind.sequential表示讓clr保留我們設定的字段布局。如果定義型別時沒有顯示指定該特性,編譯器將選擇預設的方式。c#編譯器為引用型別選擇的是layoutkind.auto方式而為值型別選擇的是layoutkind.sequential方式

5.3 值型別的裝箱與拆箱

裝箱的過程:

1、從託管堆中為新生成的引用型別物件分配記憶體,大小為值型別例項本身的大小加上額外的乙個方法表指標和乙個syncblockindex的空間

2、將值型別例項的字段拷貝到託管堆上新分配物件的記憶體中

3、返回託管堆中新分配物件的位址

拆箱和裝箱並不是嚴格意義上的互反操作。c#中拆箱之後總是緊跟乙個字段拷貝操作,這兩個操作合起來才與裝箱是真正的互反操作

拆箱的過程:

1、如果該引用為null,將會丟擲乙個nullreferenceexception異常

2、如果該引用指向的物件不是乙個期望的值型別的已裝箱物件,將會丟擲乙個invalidcastexception

3、返回乙個指向包含在已裝箱物件中值型別部分的指標

當對乙個物件執行拆箱操作時,結果必須是它原來未裝箱時的型別,例如不能將乙個已裝箱的int32物件直接轉換為乙個int16值型別

需要對值型別裝箱的幾種情況:

1、因為未裝箱的值型別沒有syncblockindex,所以不可能利用system.threading.monitor型別來同步多個執行緒對它們的訪問

2、因為未裝箱的值型別沒有方法表指標,所以我們不可能通過值型別的未裝箱例項來呼叫其上繼承而來的虛方法

3、將乙個未裝箱的值型別例項轉型為該型別實現的介面型別時需要對該例項進行裝箱

基元型別 引用型別和值型別

編譯器直接支援的資料型別稱為基元型別 primitive type 基元型別直接對映到framework類庫 fcl 中存在的型別。fcl型別在c 中對應的基元型別 c 基元型別 fcl型別 是否符合cls 說明 sbyte system.sbyte 否 有符號8位值 byte system.byt...

CLR 基元型別 引用型別和值型別

前言 今天重新看了下關於clr基元型別的東西,覺得還是有必要將其記錄下來,畢竟這是理解clr成功 之路上的重要一步,希望你也和我一樣。基元型別 編譯器直接支援的資料型別稱之為基元型別,針對那些程式設計師自定義的型別而言。所有基元型別 直接對映到fcl framework class library ...

第五章 基元型別引用型別和值型別

checked開啟時,如果發生溢位會丟擲異常,unchecked則不會排除異常。編譯器預設是關閉溢位檢查的unchecked。若要開啟溢位檢查,使用 checked 在vs的專案屬性中也可設定開啟與否。也可以給一段 新增這樣的標記。如果這段 中呼叫了另外乙個方法,這個方法是不受這個標記控制的。sys...