| 特性 | Class (Reference Type) | Struct (Value Type) |
|---|---|---|
| 基底類別 | System.Object | System.ValueType → Object |
| 記憶體配置 | Managed Heap (GC 管理) | Thread Stack / Inline in containing object |
| 變數內容 | 參考 (位址) | 實際資料值 |
| 指派語意 | 複製參考 (淺拷貝) | 複製值 (深拷貝) |
| Null 支援 | 可為 null | 不可為 null (除非 Nullable<T>) |
| 繼承 | 單一繼承、介面、多型 | 不可繼承類別、可實作介面、無多型 |
| 建構函式 | 可無參、可自訂、可靜態建構函式 | 不可無參、不可析構函式、隱含無參初始化為 0/null |
| 關鍵字限制 | 可 abstract/sealed/virtual/override/protected | 不可上述關鍵字,可覆寫 Equals/GetHashCode/ToString |
| 傳遞參數 | 傳參考 (預設) | 傳值 (預設),ref/out 可改為傳參考 |
| 銷毀時機 | GC 非確定性回收 | 離開作用域立即釋放 (Stack) / 隨容器釋放 |
// 介面實作:Struct 可實作介面,達到多型效果
interface IPerson { void GetSex(); }
struct Family : IPerson {
public string Name; public int Age; public bool Sex; public string Country;
public Person PersonRef; // 參考型別欄位
public Family(string n, int a, bool s, string c, Person p) {
Name=n; Age=a; Sex=s; Country=c; PersonRef=p;
}
public void GetSex() => Console.WriteLine($"{PersonRef.Name} is {(Sex?"boy":"girl")}");
public override string ToString() => $"{PersonRef.Name} {Age} {(Sex?"Boy":"Girl")} {Country}";
}
Point、DateTime、Guid、decimalPoint[] 連續記憶體、無 GC 壓力、Cache 友善object/介面使用會裝箱,頻繁發生效能災難struct Mutable { public int X; } 配合屬性回傳副本導致修改失效,Struct 應為不可變new MyStruct() 與 default(MyStruct) 相同,所有欄位為 0/null,不可依賴建構函式初始化邏輯IPerson p = family; 發生裝箱,改用泛型約束 where T : IPerson 避免System.Drawing.Point、Size、Rectangle:Struct,繪圖高頻運算System.Guid:Struct,16 bytes,值語意System.DateTime、DateTimeOffset、TimeSpan:StructSystem.Decimal:Struct,16 bytes,高精度數值System.Nullable<T>:Struct 包裝實值型別可為 null是否需要繼承/多型/可為 null/參考語意? → Class 否 → 是否小型 (<=16 bytes)、不可變、大量陣列、Interop? → Struct 否 → Class (預設選擇,風險最小)
Class 是面向物件的主力,Struct 是效能優化的利器。理解記憶體模型差異、避開可變 Struct 與裝箱陷阱,才能在正確場合發揮 Struct 的極致效能。下一回將探討「引用型別與實值型別的深度比較」。