object a = 1; // 裝箱:堆上創建Integer對象(值1),a引用它
object b = a; // 引用複製:b指向同一個堆對象
a = 2; // 再次裝箱:堆上創建新Integer對象(值2),a指向新對象
Console.Write(b); // 輸出1
步驟1: a = 1
堆: [Integer:1] ← a
↑
b (尚未創建)
步驟2: b = a
堆: [Integer:1] ← a
← b (同一地址)
步驟3: a = 2
堆: [Integer:1] ← b
[Integer:2] ← a (新對象,新地址)
List list1 = new List {1};
List list2 = list1; // 同一對象
list1.Add(2); // 修改對象內部狀態
Console.Write(list2.Count); // 輸出2,因指向同一對象
| 操作 | 值類型 | 引用類型(不可變) | 引用類型(可變) |
|---|---|---|---|
| 賦值 | 複製值 | 複製引用 | 複製引用 |
| 修改變量 | 互不影響 | 指向新對象,原對象不變 | 可通過任意引用修改共享狀態 |
| 典型例子 | int, struct | string, 包裝類 | class, List, Array |
`a = 2`不是修改原對象,而是讓`a`指向新對象。`b`依然忠實地指向舊對象。這正是引用語義的精髓:變量持有引用,賦值複製引用,操作作用於對象。