2010-02-22 82 views
73

我正在通過Jeffery Richter的C#閱讀CLR,它說struct是一個值類型,不能被繼承。爲什麼不?任何技術原因?還是哲學的?爲什麼C#結構不能被繼承?

+1

也許不止一個答案的問題,但所有的結構繼承System.ValueType,如果你用反光看,System.ValueType是一個抽象類:)所有的結構繼承它。如果對這個問題的答覆澄清了這一點,我認爲這將是有益的。 – Marek

+3

@Marek:在這裏閱讀我的答案的第二段,以澄清這一點:http://stackoverflow.com/questions/1978589/why-do-structs-need-to-be-boxed/1978597#1978597總之,繼承自'ValueType'對結構實例沒有結構上的暗示。實際上,就運行時而言,struct的值並不是一個真正的'System.ValueType'(即在IL中,你不能將'int'傳遞給一個沒有明確使用'box '指令)。只有盒裝結構(這是一個引用類型)真的是。 –

回答

77

編輯:顯然,這篇文章有嚴重的編輯問題。請參閱評論部分。

兩者都有一點。

在哲學,它的作品了 - 存在着階級,這是面向對象的編程「真正的」積木,有結構,這是輕量級的數據類型存儲,但允許對象樣方法需要熟悉和方便。

從技術上講,是一個「值類型」,意味着整個結構體 - 它的所有內容 - 通常存儲在任何具有該類型變量或成員的地方。作爲局部變量或函數參數,這意味着在堆棧上。對於成員變量,這意味着完全存儲爲對象的一部分。

作爲繼承是一個問題的(主要)例子,考慮如果允許結構體具有更多成員的子類型,存儲在低級別上的影響如何。任何存儲該結構類型的東西都會根據它所包含的子類型佔用不同數量的內存,這將成爲分配的噩夢。給定類的對象在編譯時將不再具有常量,已知大小,對於任何方法調用的堆棧幀來說也是如此。這不會發生在堆上分配了存儲空間的對象,而是在堆棧中或其他對象內部具有常量大小的引用。

這只是一個直觀的,高層次的解釋 - 查看擴展和更精確信息的評論和其他答案。

+0

謝謝,傑西。你的解釋給了我一些火花。就我的理解而言,OOP需要付出代價。如果只有「ref-type」,並且所有事情都發生在堆上,那麼其管理效率遠低於堆棧,則性能會很差。所以就出現了所謂的「價值型」,它爲了更好的性能而存在於堆棧中,這是因爲分配的位置以及進一步使內存使用範例使得價值型密封。 – smwikipedia

+0

......如果我們能夠找出堆棧和堆棧之外使用內存的全新範例,那麼可能會出現新的數據類型。 – smwikipedia

+0

關於使用記憶的全新範例......這是值得懷疑的。 :)使用內存的任何其他範例都可能分層堆棧或堆分配或兩者兼而有之。 (如函數式語言中的閉包,這可能值得你花時間去理解)。 –

32

因爲這是結構在.NET中的表示方式。它們是值類型,值類型沒有允許繼承的方法表指針。

+17

有人可能會補充說:他們沒有方法表指針的原因是因爲值類型被設計得儘可能的輕量級。 – bitbonk

+9

除了結構*可以*實現接口,並且使用方法表指針來調用它們... – Bevan

+1

有很多方法可以在不需要每個實例類型信息的情況下有效地支持繼承:(1)通過說「FooStruct:BarStruct」的* only *效果將會是一個限制爲BarStruct的泛型將直接訪問該類型的成員(*包括字段*); (2)通過說任何類型的'FooStruct:BarStruct'都必須通過合約綁定來使用它的繼承字段,使得通過複製現有'FooStruct'的繼承字段形成的'BarStruct'必須是有效的'BarStruct' ,並... – supercat

14

您可能會發現SO Question Why are .NET value types sealed?的相關答案。在這裏面,@logicnpECMA 335,其中規定:

8.9.10值類型繼承

  • [...]
  • 將被密封,以避免處理價值切片的併發症。
  • 此處指定的限制性更強的規則允許更高效的實施,而不會嚴重影響功能。
+1

凡「沒有嚴重影響功能」的地方,它們顯然意味着「嚴重影響功能」。 –

相關問題