首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C# 參考型別賦值機制深度解析:為何修改區域變數會影響陣列元素?

     編輯:程式設計綜合問答

現象重現

Player[] players = new Player[10];
// ... 初始化 ...
Player player = players[n];  // 區域變數指向陣列元素
player.Name = "NewName";     // 修改區域變數屬性
// 發現 players[n].Name 也變成了 "NewName"

核心原因:參考型別語義

  • Player 是 class(參考型別)。
  • 變數 players[n] 與 player 存儲的是同一個物件在堆積上的位址(引用)。
  • 賦值 player = players[n] 只是複製引用,不複製物件本身。
  • 兩個變數指向同一記憶體位置,透過任一變數修改屬性,觀察到的都是同一物件的變化。

圖解記憶體模型

Stack (棧)                    Heap (堆)
+----------------+           +---------------------+
| players[n]  ───┼──────────▶| Player Object       |
+----------------+           | Name: "NewName"     |
| player      ───┼──────────▶| HP: 100             |
+----------------+           +---------------------+

對比:實值型別

int a = 10;
int b = a;   // 複製值
b = 20;      // a 仍為 10

struct、基本型別(int, double, bool 等)為實值型別,賦值會複製資料本身。

常見解決方案

  1. 深度複製:實作 ICloneable 或建構函式 new Player(players[n]) 建立獨立副本。
  2. 使用 record (C# 9+):record Player(...) 自帶 with 運算子產生新實例:var player = players[n] with { Name = "NewName" };。
  3. 改用 struct:若語意允許,定義為 struct Player 變為實值型別(注意封箱/效能)。
  4. 不可變設計:屬性唯讀,需修改時建立新實例,避免共享狀態副作用。

除錯技巧

  • Visual Studio 監看視窗:觀察變數 Object ID(右鍵 → Make Object ID),相同 ID 即同一實例。
  • Object.ReferenceEquals(players[n], player) 回傳 true 確認共享引用。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved