備註
此內容經Pearson Education, Inc.授權從架構設計指導方針:可重複使用 .NET 程式庫的慣例、習慣用語與範式 (第2版)轉載。 該版於2008年出版,該書自那以後已於 第三版全面修訂。 此頁面的某些資訊可能已過期。
每個架構設計工具都面對的基本設計決策之一是將類型設計為類別(參考型別)或結構(實值型別)。 深入了解參考型別和實值型別行為的差異,對於做出這個選擇至關重要。
我們要考慮的引用型別和值型別之間的第一個差異是,引用型別是在堆積上配置並進行垃圾回收,而值型別則是在堆疊上配置或在包含型別中內嵌配置,并在堆疊回溯時解除分配,或當其包含的類型被解除分配時解除分配。 因此,實值型別的配置和解除分配通常比參考型別的配置和解除分配便宜。
接下來,參考型別的陣列會分行配置,這表示陣列元素只是位於堆積上之參考型別實例的參考。 值類型陣列是直接配置的,這表示陣列元素就是值類型的實例。 因此,值類型陣列的配置和解除配置比參考類型陣列的配置和解除配置便宜得多。 此外,在大部分情況下,值類型陣列表現出更好的參照局部性。
下一個差異與記憶體使用量有關。 當將實值型別轉型為參考型別或其所實作的介面時,該實值型別會被裝箱。 當轉換回值類型時,它們會被拆箱。 因為箱形物件是在堆積上配置且由垃圾回收機制管理,太多的裝箱與拆箱可能會對堆積、垃圾回收器以及應用程式的效能造成負面影響。 相反地,參考型別轉換時不會發生這類 Boxing。 (如需詳細資訊,請參閱 Boxing 和 Unboxing)。
接下來,參考類型指派會複製參考,而實值類型指派則會複製整個值。 因此,大型參考型別的指派比大型實值型別的指派便宜。
最後,引用類型會以引用方式傳遞,而值類型則以值方式傳遞。 參考型別實例的變更會影響指向 實例的所有參考。 傳值時,實值型別的實例會被複製。 當實值類型的實例變更時,它當然不會影響其任何副本。 由於不會由用戶明確建立複本,但在傳遞自變數或傳回值時隱含建立,因此可以變更的值類型可能會讓許多使用者感到困惑。 因此,實值型別應該是不可變的。
通則是,框架中大部分的類型應該是類別。 不過,在某些情況下,實值型別的特性會更適合使用 結構。
✔️ 如果型別的實例很小且通常短期或通常內嵌在其他物件中,請考慮定義結構,而不是類別。
❌ 除非類型具有下列所有特性,否則請避免定義結構:
它以邏輯方式表示單一值,類似於基本類型 (
int
、double
等)。其實例大小低於 16 個字節。
這是不可變的。
它不需要經常被打包。
在其他所有情況下,您應該將類型定義為類別。
© 2005年、2009年Microsoft公司部分。 保留所有權利。
經 Pearson Education, Inc. 許可重新刊登自 Krzysztof Cwalina 和 Brad Abrams 所著的 架構設計指導方針: 可重複使用的 .NET 程式庫慣例、慣用語和模式,第 2 版,2008 年 10 月 22 日由 Addison-Wesley Professional 發行,作為 Microsoft Windows 開發系列的一部分。