首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 結構體完整指南:實值型別語意、設計規範與效能優化

     編輯:關於C#

結構體 vs 類別核心差異

特性struct (實值型別)class (參考型別)
記憶體配置堆疊 / 內嵌陣列元素堆積 (GC 管理)
指派語意複製整個實例複製參考
繼承不可繼承 (隱性 sealed)支援繼承
預設建構函式編譯器自動產生 (全零初始化)可自訂
Null 能力不可為 null (除非 Nullable<T>)可為 null
介面實作支援支援

適用場景判斷準則

符合所有條件才考慮 struct:

  1. 邏輯上代表單一值 (如座標、日期、錢幣)
  2. 實例大小 < 16 bytes (避免複製開銷)
  3. 不可變 或 很少修改
  4. 不頻繁裝箱/取消裝箱
  5. 不需要繼承體系

設計最佳實務

// 不可變結構體 (C# 7.2+ readonly struct)
public readonly struct Point3D : IEquatable {
    public double X { get; }
    public double Y { get; }
    public double Z { get; }

    public Point3D(double x, double y, double z) {
        X = x; Y = y; Z = z;
    }

    // 覆寫 Equals/GetHashCode 避免反射開銷
    public bool Equals(Point3D other) => X == other.X && Y == other.Y && Z == other.Z;
    public override bool Equals(object obj) => obj is Point3D p && Equals(p);
    public override int GetHashCode() => HashCode.Combine(X, Y, Z);
    public static bool operator ==(Point3D a, Point3D b) => a.Equals(b);
    public static bool operator !=(Point3D a, Point3D b) => !a.Equals(b);

    // in 參數避免複製
    public double DistanceTo(in Point3D other) {
        double dx = X - other.X, dy = Y - other.Y, dz = Z - other.Z;
        return Math.Sqrt(dx*dx + dy*dy + dz*dz);
    }
}

// 可變結構體 (謹慎使用)
public struct Counter {
    private int _value;
    public int Value => _value;
    public void Increment() => _value++; // 會修改副本,若非 ref 傳遞易產生 Bug
}

效能考量

  • 陣列 Point3D[] 連續記憶體,Cache 友善,優於 Point3D[] 類別陣列
  • 避免在迴圈中以值傳遞大型結構體,改用 in / ref / Span<T>
  • readonly struct 允許編譯器優化防禦性複製
  • 實作 IEquatable<T> 避免裝箱比較

常見陷阱

  • 屬性存取回傳結構體副本:point.X = 1 編譯錯誤 (修改副本)
  • 集合初始化器隱性複製:list[0].X = 1 無效 (List 索引器回傳副本)
  • 介面呼叫導致裝箱:IEquatable<Point3D> eq = point; eq.Equals(other) 裝箱

結構體定義
實例化
記憶體配置

本文對應《叩響 C# 之門》第 5.2 節結構體教學內容

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved