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

C# 數據類型完全圖鑑:值類型、引用類型、簡單類型別名與記憶體佈局

     編輯:關於C語言

類型系統兩大陣營


System.Object (根基類)
    │
    ├─▶ 值類型 (Value Types) → 隱式繼承 System.ValueType
    │       ├─ 結構
    │       ├─ 枚舉
    │       └─ 簡單類型 (內建類型別名)
    │
    └─▶ 引用類型 (Reference Types)
            ├─ 類
            ├─ 介面
            ├─ 委託
            ├─ 字符串
            ├─ 陣列
            └─ object (別名 System.Object)

核心差異:記憶體與語義

特性值類型引用類型
儲存位置棧 (區域變數) / 內嵌在物件內 (欄位)託管堆 (對象本體),棧存引用
賦值語義**複製值** (位元級副本)**複製引用** (指向同一對象)
預設值全零位模式 (0, false, null 字符...)`null`
繼承不可繼承 (隱式 sealed),可實現介面單繼承,可實現多介面
null 能力預設不可為 null,需 `Nullable` (`T?`)天然可為 null
裝箱/拆箱發生裝箱轉為 object/介面無裝箱開銷

一、值類型深度解析

1. 簡單類型 — 關鍵字與 BCL 別名對照表

關鍵字BCL 類型大小範圍 / 精度備註
sbyteSystem.SByte8 位-128 ~ 127有符號
byteSystem.Byte8 位0 ~ 255無符號
shortSystem.Int1616 位-32,768 ~ 32,767
ushortSystem.UInt1616 位0 ~ 65,535
intSystem.Int3232 位-2,147,483,648 ~ 2,147,483,647**預設整數推薦**
uintSystem.UInt3232 位0 ~ 4,294,967,295
longSystem.Int6464 位-9.22e18 ~ 9.22e18固定 64 位,不隨平台變化
ulongSystem.UInt6464 位0 ~ 1.84e19
charSystem.Char16 位U+0000 ~ U+FFFF (UTF-16 代碼單元)**單一 Unicode 字符**,非字節
floatSystem.Single32 位±1.5e−45 ~ ±3.4e38, ~7 位有效數字IEEE 754 單精度
doubleSystem.Double64 位±5.0e−324 ~ ±1.7e308, ~15-16 位**預設浮點推薦**
decimalSystem.Decimal128 位±1.0e−28 ~ ±7.9e28, 28-29 位有效數字**貨幣/金融首選**,基 10 非基 2
boolSystem.Boolean1 位 (實際佔 1 字節)true / false**不可** 隱式轉換自整數

關鍵點補充

  • int/long **不再** 依賴機器字長,跨平台大小固定。
  • decimal 無隱式轉換至/自 `float`/`double`,避免精度靜默丟失,需顯式轉換。
  • char 為 UTF-16 代碼單元,**補充字符** (Emoji 等) 需 2 個 `char` (代理對),用 `StringInfo` 或 `Rune` (Net Core 3.0+) 處理。
  • 字面量後綴:`123L` (long), `1.5F` (float), `1.5M` (decimal), `1.5` (double)。

2. 結構類型


// 定義
public struct Point3D {
    public int X, Y, Z;           // 欄位
    public readonly double Dist;  // 唯讀欄位 (C# 7.2+)
    public Point3D(int x, int y, int z) { X=x; Y=y; Z=z; Dist = Math.Sqrt(x*x+y*y+z*z); }
    public void Translate(int dx, int dy, int dz) { X+=dx; Y+=dy; Z+=dz; } // 可變方法
    public override string ToString() => $"({X},{Y},{Z})";
}

// 使用
var p1 = new Point3D(1,2,3); // 棧分配,無 new 也可但欄位需全部初始化
var p2 = p1;                 // **值複製**,p2 獨立於 p1
p2.Translate(10,0,0);
Console.WriteLine(p1); // (1,2,3) 未受影響
Console.WriteLine(p2); // (11,2,3)

結構 vs 類 選型指南

  • ✅ **用結構**:小型 (<16 bytes)、不可變、值語義、高頻分配 (避免 GC 壓力)、邏輯上為單一值 (座標、顏色、日期區間)。
  • ❌ **避免結構**:大型、可變、頻繁裝箱、作為基類、需多態。
  • readonly struct (C# 7.2+) 編譯器強制不可變,避免防禦性複製開銷。

3. 枚舉類型


// 底層類型預設 int,可指定 byte/short/long
public enum FileAccess : byte { Read = 1, Write = 2, ReadWrite = 3 }

// Flags 屬性:位標志組合
[Flags]
public enum Permissions : uint {
    None = 0, Read = 1, Write = 2, Execute = 4, Admin = Read | Write | Execute
}

var p = Permissions.Read | Permissions.Write; // 3
bool hasWrite = p.HasFlag(Permissions.Write); // true

二、引用類型核心

類型關鍵字/語法說明
類class引用語義、繼承、多態、GC 管理
介面interface契約、多實現、預設方法 (C# 8+)
委託delegate類型安全函數指針、多播、事件基礎
字符串string / System.String**不可變引用類型**,特殊字面量語法、驻留池
陣列T[], T[,], T[][]繼承 System.Array,固定大小、協變性
objectobject / System.Object所有類型終極基類,裝箱目標

字符串特殊行為

  • 不可變:`s.Replace("a","b")` 返回**新字符串**,原值不變。
  • 字符串駐留:編譯期常量字面量自動駐留,`string.Intern()` 手動駐留,`==` 比較內容而非引用 (運算符重載)。
  • 高頻拼接用 `StringBuilder` / `string.Concat` / 字串插值。

陣列協變性 (隱患)


string[] strings = { "a" };
object[] objects = strings; // 隱式轉換,編譯通過
objects[0] = 123;           // 運行時拋 ArrayTypeMismatchException

建議用 `List` / `ImmutableArray` 避免協變性陷阱。

三、裝箱與拆箱:值類型穿越引用世界


int i = 42;
object o = i;       // 裝箱:堆分配 object,複製值
int j = (int)o;     // 拆箱:類型檢查 + 複製值回棧

// 隱式裝箱陷阱
var list = new ArrayList(); // 非泛型集合
list.Add(42);               // 每次 Add 都裝箱!
// 改用 List 避免裝箱

效能影響

  • 分配堆記憶體 + 複製值 + GC 壓力。
  • 熱路徑**嚴禁**裝箱:用泛型、`Span`、`ref struct` 避免。

四、可空值類型


int? x = null;          // Nullable
int? y = x + 10;        // C# 7.3+ 支援 lifted 運算符:null + 10 = null
int z = x ?? -1;        // 空合併運算符
bool has = x.HasValue;  // 檢查
int val = x.Value;      // 取值 (若 null 拋異常)
int val2 = x.GetValueOrDefault(); // 安全取值

五、記憶體佈局可視化


// 類實例在堆
class Node { public int Id; public Node Next; }
Node n = new Node { Id = 1 };
// 堆: [SyncBlockIndex][TypeHandle][Id=1][Next=ref] → 另一 Node 對象

// 結構在棧/內嵌
struct Point { public int X; public int Y; }
Point p = new Point { X=1, Y=2 };
// 棧/父對象內: [X=1][Y=2] (連續 8 bytes,無對象頭)

// 陣列在堆
int[] arr = { 1, 2, 3 };
// 堆: [SyncBlockIndex][TypeHandle][Length=3][1][2][3] (元素內嵌)

六、類型選型決策速查

需求推薦類型
整數計數/索引int
大整數/時間戳long
金額/匯率/精確小數decimal
科學計算/圖形/物理double
單字符/字符處理char / Rune
真/假邏輯bool
坐標/向量/小型不可變數據readonly struct
業務實體/服務/複雜對象class
契約/插件點interface
回調/事件/策略delegate / Func/Action
文本/序列化/配置string
同類型集合/高效隨機訪問T[] / List / ImmutableArray

結語

精通 C# 類型系統,是寫出**高效、正確、可維護**代碼的基石。牢記:**值類型傳值、引用類型傳引用、裝箱有代價、結構要小、Decimal 做錢、String 不可變**。選對類型,事半功倍。

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