2011-07-30 60 views
6
之間進行選擇

在C#中的MSDN文章名爲Choosing Between Classes and Structures給出了以下建議:類和結構

考慮定義一個類的結構,而不是如果 類型的實例是小的和普遍短命或通常是嵌入 其他對象。

不要定義的結構,除非該類型具有以下所有 特徵:

It logically represents a single value, similar to primitive types 

(整數,雙,和等等)。

It has an instance size smaller than 16 bytes. 

It is immutable. 

It will not have to be boxed frequently. 

如果這些條件的一個或多個不滿足,創建參考 型代替的結構。如果不遵守這一指導方針, 會對性能產生負面影響。

我不知道D的答案會是什麼。到目前爲止,我只是在所有不需要多態性的情況下使用了結構。我不知道大小是否也是一個考慮因素。或其他任何東西。

+1

你說的是編程語言D嗎?如果是這樣,你正在談論的是與C#完全不同的語言 - 開始嘗試將來自一種語言和平臺的推薦應用到另一種語言是一個非常糟糕的主意。 –

+3

@John Skeet--這不就是他問這個問題的原因。他閱讀了關於適用於C#的東西,並詢問D的情況是怎樣的。 – iandotkelly

+0

@Jon Skeet。是的,我正在談論D.對於混淆抱歉。我意識到,語言是不同的,這只是讓我想知道。 – fwend

回答

7

我會說,這個建議肯定不會適用於D.

結構是值類型。類是引用類型。結構通常在堆棧上(儘管它們可以在堆上,並用指針指向)。類在堆上。結構沒有繼承或多態性。類具有繼承性和多態性。

這是非常在D中使用結構是很常見的。我認爲一般規則是,如果某些東西不需要有多態性,它應該是一個結構。 主要原因在結構上選擇一個類的原因是因爲你想要繼承和多態。

第二個原因是,如果它只是更有意義的類型是一個引用類型(例如一個容器應該可能是一個類,因爲每次你將它傳遞給一個函數時複製它不會很好)。結構可以有引用語義,但它只是使用類更清潔。最後,如果一個類型中包含大量數據,並且只要將它傳遞給一個函數就不需要它的副本,那麼使它成爲一個類並且只有它是更有效的當你真的需要時複製它(儘管你可以選擇總是通過ref來代替它)。

D的結構比C#的結構更加奇特,因爲它們具有析構函數和postblit constructors。 D中也沒有自動裝箱問題,因爲D使用模板(類似於C++,儘管功能更強大,使用也更容易),而不是泛型。如果你需要一個指向結構的指針,很容易做到。所以,我真的不認爲對於C#的建議適用於D.

在我看來,在C#建議從兩個問題源於:

  1. 該結構是值類型,因此有事實價值語義。
  2. C#中的結構必須處理自動裝箱並且必須非常擔心複製的成本。

結構是也是d值類型,但他們足夠強大,能夠有引用語義,如果你想,並增設postblit構造函數和析構函數,使他們遠比更有用什麼你可以用C#中的結構來完成。而且由於D沒有自動裝箱,所以對自動裝箱的擔心不適用於D.你仍然不希望你的結構變得龐大,因爲除非你通過ref,否則當它們通過時它們會被複制到一個函數,但它絕對不像在C#中那麼大。在這方面它更符合C++。

而關於不變性的建議不適用於在所有到D. D結構經常是可變的,如果它們不是,它將是一個大問題。例如,範圍通常是作爲結構實現的,如果你不能改變它們,這是不可能的。

所以,不,我不認爲C#的建議真的適用於D.這兩種語言之間的情況完全不同。將D的結構看作沒有任何基類並且不能派生的C++類會更好,因爲它比C#的結構更接近實際的結果。

+0

結構具有引用語義不需要Post-blit構造函數。一個.net結構包裝一個可變引用類型的私有字段,該類型只能在其構造函數中設置,通常會顯示引用語義,無論是否需要它,因爲該結構的副本將引用與原本的。我希望postblit構造函數的目的是允許一個結構保存對堆對象的唯一引用,以便能夠直接更改該對象,而不是構造一個不同於所需方式的新對象。 – supercat

1

結構是按值傳遞這樣的尺寸的確是一個考慮因素(儘管能避免與refin

大多是當你需要按值傳遞只(更改對象不該你應該使用結構」或者它是一個短壽命的對象,它的壽命足夠短,可以保留在堆棧上(就像在std.algorithm模塊中看到的範圍對象;所有函數幾乎全部返回一個結構)

個人I定義了數據對象(單值子句)的結構,如2d點和一些帶有一些便利功能和操作符超載的角度ng爲他們定義

0

相同的建議一般適用於D在C#中 - 他們幾乎是相同的概念。

唯一的例外是拳擊建議 - 它並不適用,因爲拳擊並沒有真正原生的D.

8

在d存在的,也有從C#,使得它的幾個關鍵差異習慣使用struct更頻繁:

  1. 有沒有自動裝箱,因爲它解決的問題通常與模板解決。

  2. 現在,垃圾收集器效率較低。

  3. 如果您想要引用語義,大多數情況下指向結構體的指針都可以很好地工作。 (唯一的一個主要例外是指向具有重載算術或索引操作符的結構的指針表現異常,因爲這些操作被視爲指針算術而不是調用操作符重載。)此外,可以使用new運算符輕鬆地爲堆分配結構。

  4. 結構可以有確定性的析構函數(不是終結器),複製構造函數等,所以你可以用C++做類似的魔術。

我想說一個結構應使用任何時候你不需要多態性,不會需要它的未來,不需要引用語義,或者如果你需要確定的破壞,拷貝構造,等等。如果你需要多態,那麼你肯定需要使用一個類。

如果您不需要多態但希望引用語義,那麼指向堆分配結構或最終類的指針都可以正常工作。最後一個類在語法上稍微好一點,並且在重載算術運算符時不會碰到怪異的角落情況。通過沒有vtable或監視器,結構可以避免幾個字節的開銷。如果這些都不重要,那麼這只是個人喜好的問題。