# 一起學 Class and Struct (C#) ###### tags: `C#` `Core` `ReferenceType/ValueType` `Stack/Heap` ## 學習目標 了解`Class`和`Struct`的差異和使用時機 ## 目錄 [TOC] # Class與Struct 直接說明其核心差異其實很簡單如下 * Class 是參考類型(Reference type) * Struct 是實值類型(Value type) 但什麼是<font class="red">**參考類型**</font>以及<font class="red">**實值類型**</font>?其中又有什差異?接下是我們要是我們要了的問題 # 參考類型、實值類型 ## 初步了解 C#語言中有兩個主要類別分別為 ### 參考類型(Reference type) 1. 關鍵字定義:class、interface、delegate、record 2. 內建(Built-in)類型:dynamic、object、string ### 實值類型(Value type) 1. 關鍵字定義:struct 2. 內建(Built-in)類型:bool、byte、int、char.....等等 > 官方參考文件 > [Reference types](https://docs.microsoft.com/bs-latn-ba/dotnet/csharp/language-reference/keywords/reference-types) > [Value types](https://docs.microsoft.com/bs-latn-ba/dotnet/csharp/language-reference/builtin-types/value-types) 除了文件上面的紀錄外想要快速區分其定義也可以查看其繼承,如果有繼承[System.ValueType](https://docs.microsoft.com/en-us/dotnet/api/system.valuetype?redirectedfrom=MSDN&view=net-6.0)就會是實值類型。 知道定義後接下來說說兩個之間的不同 ## 差異比較 這邊主要透過文章[Choosing Between Class and Struct](https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/choosing-between-class-and-struct)來認識,以下除了整理成自己方便理解的筆記外也外加了許多參考資料。 ### 資源配置與釋放 其資源分配和回收的方式不同如下: * Reference types:存放於Heap會由garbage-collected(GC)去清理 * Value types:存放於Stack函式結束後直接釋放 這張圖清楚描述了其配置和釋放的不同,其Heap會由GC的機制下去自動釋放 <img src="https://www.codeproject.com/KB/Articles/6importentStepsDotNet/13.jpg"/> > 圖片來源:[Six Important .NET Concepts: Stack, Heap, Value Types, Reference Types, Boxing, and Unboxing](https://www.codeproject.com/Articles/76153/Six-important-NET-concepts-Stack-heap-value-types#Stack%20and%20Heap) ### 陣列(array)使用差異 因為其資源配置的方式進而影響array內的元素配置方式也會不相同,一般來說Value types對於配置以釋放來說所消耗的資源會更少。 ### 記憶體配置 我們透過以下圖片來了解其儲存的差異,分別為Stack Memory和Heap Memory這邊可以看其差異, 1. Value types:儲存時回記錄在Stack當中 2. Reference types:會在Stack記錄Heap的位置並且將資料存放在Heap的當中  > 圖片來源:[Stack Vs Heap Memory - C#](https://www.c-sharpcorner.com/article/stack-vs-heap-memory-c-sharp/) 這邊需要而外提到[Boxing and Unboxing](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing)之行為,其程式碼如下 ```csharp= int i = 123; // The following line boxes i. object o = i; ``` ```csharp= o = 123; i = (int)o; // unboxing ``` 這樣的轉換操作會把Value types轉變成Reference types方式去做儲存,除了消失Stack儲存的好處外,過多的轉換也可能造成Heap和garbage-collected對於程序造成效能上的影響。 ## 複製操作 因為Reference types的儲存資料的特性,在執行複製候只需要複製位址即可,至於Value types則會需要完整的複製整個數值,因此在資源花費上Reference types會更加便宜。 ## 複製後值變更 Reference types執行複製後其位址還是指向同一份資料,因此作變更時所有指向同一個位址的資料全部都會影響。 Value types的則是完整複製,故在變更的時候不會影響任何複本,但是此行為不是由使用者定義明確的複製操作是<font class="red">**隱含建立**</font>,可能會造成許多使用者混淆。 # 如何選擇 這邊直接使用官方解釋 通常有以下的狀況會考慮使用`struct` * 實例小、參數短期使用、嵌入在其它物件內 評估方式可確認是否有其特性 * 以邏輯方式表示單一值,類似基本類型(int、double...等) * 實例大小小於16 bytes * 不可變 * 不須經常boxed **除此以外的所有情況都直接定義為Class** > 來源依樣同[Choosing Between Class and Struct](https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/choosing-between-class-and-struct) # 其它差異 除了儲存方式以外在C#的設計上也有針對`Struct`也有些限制,因為某些限制會因為C#的版本被開放,這邊列一下目前無法還有的限制 * 無法繼承其它類別或結構,且不能為類別的基底 * 結構可以實作介面 * 無法實作完成項(過去稱為**解構子**) # 結論 整體來說最核心的差異就是儲存方式的不同,可以透過此文章[Stack Vs Heap Memory - C#](https://www.c-sharpcorner.com/article/stack-vs-heap-memory-c-sharp/)再去強化儲存機制上的認知,儘管使用`struct`的情境不多,但是有這樣的學過一輪也算是對C#有更深一步的認識,未來在實作上其概念也能更清楚。 <br/> --- 相關參考來源: [Stack Vs Heap Memory - C#](https://www.c-sharpcorner.com/article/stack-vs-heap-memory-c-sharp/) [Choosing Between Class and Struct](https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/choosing-between-class-and-struct) [C# Struct 使用注意事項](https://blog.opasschang.com/csharp-struct-usage-notes/) [結構類型的設計限制](https://docs.microsoft.com/zh-tw/dotnet/csharp/language-reference/builtin-types/struct#limitations-with-the-design-of-a-structure-type) <style> .red{color: red;} </style>
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.