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

C# 結構 完整指南:值型別語意、記憶體模型與進階佈局控制

     編輯:關於C語言

前言:結構 vs 類別

結構 (struct) 與類別 (class) 同樣支援屬性、方法、建構函式、介面實作,但本質差異巨大:

特性類別 (參考型別)結構 (值型別)
記憶體配置Managed HeapStack (或內嵌於父物件)
變數指派複製參考 (雙方指向同一物件)複製實體值 (獨立副本)
方法傳遞傳參考 (預設)傳值 (建立副本)
繼承單一繼承,可為基底類別不可繼承其他結構/類別,隱含繼承 System.ValueType
預設建構函式隱含無參建構函式隱含無參建構函式 (將所有欄位歸零),不可自訂無參建構函式
Null 值可為 null不可為 null (除非包裝於 Nullable<T>)

堆疊 vs 堆積:效能啟示

結構實體建立於堆疊,配置/釋放極快 (指標遞增/遞減),無 GC 壓力。適合 小型、不可變、生命週期短、大量建立 的資料載體 (如座標點、複數、日期時間)。但頻繁傳遞大型結構會導致堆疊複製開銷,此時應改用類別或 ref/in 傳遞。

建構函式與初始化規則

  • 可自訂 有參數 建構函式,必須對所有欄位賦值 (編譯器強制)。
  • 無法定義無參建構函式;new Struct() 呼叫的是預設建構函式 (全欄位歸零)。
  • 欄位不可在宣告時初始化 (C# 6.0 前);C# 6.0+ 允許 public int X { get; set; } = 1; (自動屬性),但仍不支援欄位初始化器。
  • 未使用 new 宣告變數時,欄位維持未指派狀態,必須在使用前逐一賦值。

介面實作:結構也能多型


public interface IImage { void Paint(); }

public struct Picture : IImage
{
    public void Paint() { /* 繪圖邏輯 */ }
    private int _x, _y, _z;
}

結構實作介面時,若透過介面變數存取,會發生 裝箱,產生堆積配置,喪失值型別效能優勢。避免裝箱技巧:使用泛型約束 where T : IImage 或 C# 7.2+ readonly struct 配合 in 參數。

進階記憶體佈局控制:StructLayout 與 FieldOffset

預設 LayoutKind.Sequential 依宣告順序排列。透過 [StructLayout(LayoutKind.Explicit)] 可精確控制每個欄位位移,實現 聯集 效果:


[StructLayout(LayoutKind.Explicit)]
public struct TestUnion
{
    [FieldOffset(0)] public int IntValue;
    [FieldOffset(0)] public double DoubleValue;
    [FieldOffset(0)] public char CharValue;
    [FieldOffset(0)] public byte ByteValue;
}
// 所有欄位共用相同 8 位元組記憶體 (以最大者為準)

另一範例:手工拆解 long 為兩個 int:


[StructLayout(LayoutKind.Explicit)]
public struct TestExplicit
{
    [FieldOffset(0)] public long LongValue;
    [FieldOffset(0)] public int LowInt;
    [FieldOffset(4)] public int HighInt;
    [FieldOffset(8)] public double DoubleValue; // 覆蓋前 8 bytes
}

此技術常用於 P/Invoke 呼叫原生 API、高效能序列化、硬體暫存器映射。

唯讀欄位 (readonly) vs 常數 (const)

  • const:編譯期常數,必須在宣告時以常數運算式初始化,隱含 static,僅限基本型別、string、enum 或 null 參考。
  • readonly:執行期常數,可在宣告或建構函式中賦值,支援任意型別 (含陣列、物件實例),可為 static 或實例欄位。

跨組件版本控制陷阱:const 值會在編譯期內嵌至呼叫端 IL,修改後需重編譯所有參考組件;static readonly 則在執行期讀取,僅需重編譯定義組件。

結語

結構是 C# 高效能程式設計的利器。掌握值型別語意、記憶體佈局控制、避免裝箱技巧,能編寫出既安全又極速的系統級程式碼。記住:小而不可變 是結構的最佳應用場景。

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