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

C# 結構體 完整解析:值型別語意、效能優勢與使用陷阱

     編輯:關於C#

基本宣告


public struct Book
{
    public int Price;
    public string Title;
    public string Author;
}

class Test
{
    static void Main()
    {
        Book bk = new Book(); // 不用 new 也可:Book bk;
        bk.Price = 23;
        bk.Title = "書名";
        bk.Author = "作者";
        Console.WriteLine($"{bk.Title} {bk.Author} {bk.Price}");
    }
}

結構 vs 類別:核心差異對照

特性結構類別
型別分類值型別參考型別
記憶體配置Stack(區域變數) / Inline 在物件內Heap
指派行為複製整個值複製參考(指向同一物件)
預設值所有欄位為 0/null/falsenull
繼承不可繼承其他結構/類別,不可為基底類別單一繼承,可為基底
介面可實作介面可實作介面
建構函式不可定義無參建構函式,需帶參數可定義無參建構函式
解構函式不可定義可定義
欄位初始化不可在宣告處初始化(除非 const/static)可在宣告處初始化
Null 能力可用 Nullable<T> (T?) 包裝原生可為 null
Boxing/Unboxing轉為 object/介面時發生天生是參考型別

值型別複製語意實測


struct Point { public int X, Y; }

var p1 = new Point { X = 1, Y = 2 };
var p2 = p1; // 複製值
p2.X = 10;
Console.WriteLine(p1.X); // 1 (未改變)
Console.WriteLine(p2.X); // 10

⚠️ 常見陷阱與避坑指南

  1. 可變結構體是魔鬼:方法修改結構體欄位實際修改的是副本。
    ✅ 設計為不可變:欄位 readonly、屬性唯讀、方法回傳新實例。
  2. Boxing 效能陷阱:object o = myStruct; → Heap 配置 + 複製。頻繁裝箱導致 GC 壓力。
    ✅ 避免在熱路徑將結構體當 object/介面使用;泛型集合 List<T> 避免裝箱。
  3. 預設值陷阱:new MyStruct() 與 default(MyStruct) 相同,所有欄位歸零。若 0 非合法狀態(如 Id=0),需額外驗證或用類別。
  4. 大小限制:建議 < 16 bytes(4 個 int / 2 個 double)。超過會因頻繁複製拖慢效能,改用類別。
  5. 避免在介面變數中儲存結構體:IEnumerable<Point> 會導致逐項裝箱。

適用場景

  • 小型、不可變、邏輯上為「值」的資料:座標點、複數、日期時間區間、錢幣金額、RGB 色彩。
  • 高效能陣列:Point[] 連續記憶體、無參考開銷、Cache 友善。
  • 互通性:P/Invoke、硬體緩衝區、檔案格式對應的固定大小資料結構。

現代 C# 進階:readonly struct / ref struct (C# 7.2+)


// 編譯器強制不可變,避免防禦性複製
public readonly struct ImmutablePoint
{
    public int X { get; }
    public int Y { get; }
    public ImmutablePoint(int x, int y) { X = x; Y = y; }
}

// 僅能存在於 Stack,不能逃逸到 Heap(不可用於 async/迭代器/Boxing)
public ref struct StackOnlySpan
{
    public Span<byte> Data;
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved