分享方式:


在類別和結構之間選擇

注意

此內容是由 Pearson Education, Inc. 授權轉載自架構設計指導方針:可重複使用 .NET 程式庫的慣例、慣用語和模式,第 2 版。 該版於 2008 年出版,該書自那以後已於第三版進行了全面修訂。 此頁面上的某些資訊可能已過期。

每個架構設計工具都會面對的基本設計決策之一,就是將類型設計為類別 (參考型別) 或結構 (實值型別)。 充分瞭解參考型別與實值型別在行為上的差異,對於做出這個選擇非常重要。

我們將考慮的參考型別與實值型別之間的第一個差異是,參考型別會配置在回收的堆積和記憶體上,而實值型別則會配置在堆疊上,或內嵌在包含型別上,並在堆疊回溯時或其包含類型解除配置時解除配置。 因此,實值型別的配置和解除配置的成本通常比參考型別的配置和解除配置的成本更低。

接下來,參考型別的陣列會以換行方式配置,這表示陣列元素只是位於堆積上之參考型別執行個體的參考。 實值型別陣列會內嵌配置,這表示陣列元素是實值型別實際的執行個體。 因此,實值型別陣列的配置和解除配置的成本會遠比參考型別陣列的配置和解除配置的成本來得低。 此外,在大部分情況下,實值型別陣列會呈現較佳的參考位置。

下一個差異與記憶體使用量有關。 強制轉型為參考型別或其實作的其中一個介面時,實值型別會進行 Boxed。 當強制轉型回實值型別時,它們會進行 Unboxed。 因為 Box 是配置在堆積上且被回收記憶體的物件,所以過多 Boxing 和 unboxing 可能會對堆積、記憶體回收行程,以及最終是應用程式的效能造成負面影響。 相反地,不會在參考類型強制轉型時發生這類 Boxing。 (如需詳細資訊,請參閱 Boxing 和 Unboxing)。

接下來,參考型別指派會複製參考,而實值型別指派則會複製整個值。 因此,大型參考型別的指派成本比大型實值型別的指派成本更低。

最後,參考型別會以傳址方式傳遞,而實值型別則是以傳值方式傳遞。 對參考型別的執行個體所做的變更會影響所有指向執行個體的參考。 實值型別執行個體會在以傳值方式傳遞時複製。 變更實值型別的執行個體時,它必然不會影響其任何複本。 由於不會由使用者明確建立複本,而是會在傳回引數或傳回值時隱含建立,因此可以變更的實值型別可能會對許多使用者造成混淆。 因此,實值型別應該為不可變。

作為經驗規則,架構中大部分的類型應該為類別。 不過,在某些情況下,實值型別的特性會使它更適合使用結構。

✔️ 如果類型的執行個體很小,且通常短期或通常內嵌在其他物件中,請考慮定義結構,而不是類別。

❌ 除非類型具有下列所有特性,否則請「避免」定義結構:

  • 其以邏輯方式表示單一值,類似於基本類型 (intdouble 等)。

  • 其執行個體大小低於 16 個位元組。

  • 類型為不可變,

  • 而且不需要經常進行 Box。

在所有其他情況下,您應該將類型定義為類別。

Portions © 2005, 2009 Microsoft Corporation. 著作權所有,並保留一切權利。

獲 Pearson Education, Inc. 的授權再版,從 Krzysztof Cwalina 和 Brad Abrams 撰寫,並在 2008 年 10 月 22 日由 Addison-Wesley Professional 出版,作為 Microsoft Windows Development Series 一部份的 Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition 節錄。

另請參閱