在 C# 中,?結構體(struct)? 是一種值類型數據類型,適用于封裝小型數據組。與類(class)不同,結構體在棧(Stack)上分配內存,且賦值時會發生值復制。以下是結構體的核心特性和用法:
?結構體核心特點?
結構提供了一種輕量級的數據類型,適用于表示簡單的數據結構,具有較好的性能特性和值語義:
- 值類型?:賦值時復制整個數據,修改副本不影響原數據。
- 結構可帶有方法、字段、索引、屬性、運算符方法和事件,適用于表示輕量級數據的情況,如坐標、范圍、日期、時間等。
- 結構可定義構造函數,但不能定義析構函數。但是,您不能為結構定義無參構造函數。無參構造函數(默認)是自動- 定義的,且不能被改變(C# 10 前不能定義無參構造器,所有字段需在構造器中初始化。)。
- 與類不同,結構不能繼承其他的結構或類。
- 結構不能作為其他結構或類的基礎結構。
- 結構可實現一個或多個接口。
- 結構成員不能指定為 abstract、virtual 或 protected。
- 當您使用 New 操作符創建一個結構對象時,會調用適當的構造函數來創建結構。與類不同,結構可以不使用 New 操作符即可被實例化。
- 如果不使用 New 操作符,只有在所有的字段都被初始化之后,字段才被賦值,對象才被使用。
- 結構變量通常分配在棧上,這使得它們的創建和銷毀速度更快。但是,如果將結構用作類的字段,且這個類是引用類型,那么結構將存儲在堆上。
- 結構默認情況下是可變的,這意味著你可以修改它們的字段。但是,如果結構定義為只讀,那么它的字段將是不可變的。
?結構體 vs 類?
特性 | 結構體(struct) | 類(class) |
---|---|---|
類型 | 值類型(棧內存) | 引用類型(堆內存) |
繼承 | 不支持 | 支持 |
默認構造器 | C# 10 前無隱式無參構造器 | 有隱式無參構造器 |
賦值行為 | 復制值 | 復制引用 |
適用場景 | 小型、頻繁創建的數據 | 復雜對象、需要繼承的場景 |
?結構體定義示例?
public struct Point
{public int X;public int Y;// C# 10+ 允許顯式無參構造器public Point(){X = 0;Y = 0;}public Point(int x, int y){X = x;Y = y;}public void Print() => Console.WriteLine($"({X}, {Y})");
}
?使用結構體?
// 創建結構體實例
Point p1 = new Point(10, 20);
Point p2 = p1; // 值復制p2.X = 30; // 修改副本不影響原數據
p1.Print(); // 輸出: (10, 20)
p2.Print(); // 輸出: (30, 20)// 使用無參構造器(C# 10+)
Point p3 = new Point();
p3.Print(); // 輸出: (0, 0)
?何時使用結構體??
- 數據量小?:字段較少(通常少于 16 字節)。
- 不可變需求?:設計為不可變類型(所有字段只讀)。
- ?避免裝箱?:減少值類型與引用類型轉換的性能損耗。
- ?高頻實例化?:如游戲中的坐標計算,減少堆內存壓力。
?注意事項?
- 避免大型結構體?:復制成本高,可能降低性能。
- ?慎用可變結構體?:修改副本可能導致預期外的行為。
- ?構造器必須初始化所有字段?:否則編譯報錯。
- ?實現接口需謹慎?:可能導致裝箱操作(將結構體轉為 object 或接口類型時)。
通過合理使用結構體,可以優化內存分配和程序性能,但需根據場景權衡值與引用類型的優缺點。