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

C# 基礎觀念釐清:值類型與參考類型、參數修飾符、類別與物件、記憶體模型

     編輯:關於C#

值類型 vs 參考類型

特性值類型參考類型
基底類別System.ValueTypeSystem.Object
範例int, double, bool, struct, enumclass, string, array, delegate, interface
記憶體配置堆疊 或 內嵌於參考型別堆積
變數儲存內容資料本身指向堆積物件的參考
指派語意複製資料複製參考
null 能否指派不可 (除非 Nullable<T>)可
預設值0/false/結構體零值null

記憶體圖解

// 區域變數
int a = 10;           // Stack: [a: 10]
int b = a;            // Stack: [b: 10] 獨立副本
b = 20;               // a 仍為 10

// 參考型別
var p1 = new Person { Name = "A" }; // Stack: [p1: ref#100] Heap#100: {Name:"A"}
var p2 = p1;                        // Stack: [p2: ref#100] 共同指向 Heap#100
p2.Name = "B";                      // Heap#100.Name 變 "B",p1.Name 也變 "B"

// 參考型別做為參數
void M1(Person p) { p.Name = "C"; } // 修改 Heap 物件內容,呼叫端可見
void M2(Person p) { p = new Person(); } // 修改區域參考,呼叫端不可見

方法參數修飾符

修飾符值類型行為參考類型行為使用時機
(無)複製值,修改不影響原變數複製參考,修改物件內容影響原物件,重新指派參數不影響原變數預設,唯讀輸入
ref傳遞變數位址,修改直接影響原變數傳遞參考位址,修改參考本身 (指向新物件) 影響原變數需雙向資料流、交換值
out同 ref,但呼叫端變數無需初始化,方法內**必須**指派同 ref,方法內必須指派多重回傳值、TryParse 模式
in (C# 7.2+)唯讀 ref,防止意外修改,大型結構體避免複製開銷唯讀 ref高效能唯讀傳遞
params參數陣列,呼叫端可傳可變參數或陣列同左參數個數不定

ref/out 重載規則

  • ref 與 out **不能**作為重載區別(CLR 視為相同簽章)。
  • ref/out 與無修飾符**可以**重載。
  • 範例:
    void M(int x) { }          // OK
    void M(ref int x) { }      // OK,與上重載
    void M(out int x) { }      // 編譯錯誤:與 ref 衝突

類別、物件、參考三者關係

  • 類別:藍圖/模板,定義欄位、屬性、方法。編譯後為中繼資料。
  • 物件:類別的具體實例,佔據堆積記憶體,擁有唯一身分。
  • 參考:指向物件的「遙控器」,儲存在堆疊/暫存器,32/64 位元整數大小。
Person p = new Person(); // 1. new 在堆積配置物件 2. 呼叫建構函式初始化 3. 回傳參考指派給 p
// p 是參考,Person 是類別,堆積上的是物件

值類型作為參考型別欄位(拳擊/解拳)

class Box { public int Value; }
var b = new Box(); // Heap: Box { Value: 0 }
b.Value = 10;      // 直接修改 Heap 上的 int,無拳擊

// 介面參考導致拳擊
IComparable c = 10; // int 被拳擊成物件放入堆積
int v = (int)c;     // 解拳

常見誤區

誤區正確觀念
struct 一定在 Stackstruct 作為 class 欄位/陣列元素/boxing 時在 Heap
class 一定在 HeapC# 9+ `record struct`、stackalloc、ref struct 可在 Stack
string 是值類型string 是參考類型,但不可變、行為類值類型
ref 傳遞物件ref 傳遞的是參考的位址,非物件本身
out 必須在方法一開始指派out 必須在方法返回前確定指派,可在中間邏輯後指派

總結

掌握 值/參考類型記憶體語意、參數修飾符雙向流向、類別/物件/參考三元關係,是寫出正確、高效能 C# 代碼的基石。特別注意:預設參數傳遞為「值傳遞」(值類型複製值、參考類型複製參考),`ref`/`out`/`in` 才改變此語意。面試、除錯、效能優化時,畫記憶體圖是最有效的思考工具。

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