C# 沒有傳統指標,但參考型別變數的行為常被初學者誤解為「指標」。本文透過簡潔例子,釐清變數重新指向與修改物件屬性的本質區別,助你建立正確心智模型。
當你宣告 Foo a = new Foo();,a 在堆疊上存儲指向堆積上 Foo 實例的引用(地址)。
Foo a = c; // a 指向 c 所指的物件
Foo b = new Foo(); // b 指向新物件
Foo a = b; // a 現在指向 b 所指的物件,不再指向 c
// 之後對 a 的任何操作(包括重新指向)都作用於 b 指向的物件
關鍵:a = b 是引用賦值,讓 a 與 b 指向同一物件。原本 a 指向的 c 物件若無其他引用,將面臨 GC 回收。
Foo b = new Foo();
Foo a {
get { return b; }
}
// a 無法被重新指向(唯讀屬性)
// 但 a.bar = 5; 是合法的,且會修改 b 的 bar 屬性
解析:
a = c; ❌ 編譯錯誤:a 是唯讀屬性,無法重新指向。a.bar = 5; ✅ 合法:存取 a 回傳的物件(即 b),修改其 bar 欄位。本質上,a.bar = 5 等同於 b.bar = 5。屬性 get 回傳引用,隨後的成員存取運作於該引用指向的物件。
| 操作 | 語法 | 本質 | 影響 |
|---|---|---|---|
| 變數重新指向 | a = c; |
改變堆疊上變數 a 存儲的地址 |
a 指向新物件,原物件不受影響(除非無其他引用被 GC) |
| 修改物件屬性/欄位 | a.bar = 5; |
透過 a 存儲的地址找到物件,修改其內部資料 |
所有指向該物件的變數(a、b 等)觀察到的內容都改變 |
a = b 是換標籤;a.x = 1 是改實體內容。C# 參考型別變數行為其實很簡單:變數存地址,賦值傳地址,成員存取跟著地址找物件改內容。搞懂這點,「指標」困惑自然冰釋。