C# 链表元素的引用地址分析

📅 2026/7/24 21:47:16
C# 链表元素的引用地址分析
有以下现象public class Chinese { public string Name { get; set; } public int Age { get; set; } public int Height { get; } }var chiPersons new ListChinese { new Chinese { Name 张三, Age 25 }, new Chinese { Name 李四, Age 30 }, new Chinese { Name 王五, Age 28 } }; //创建新链表使用存在的chiPersons 填充 ObservableCollectionChinese MachinePositionList new ObservableCollectionChinese(chiPersons); MachinePositionList[0].Age 100; //chiPersons 第一个元素会跟随更改 var a chiPersons[0].Age; //看到chiPersons 第一个元素的也变成了100 //我天真的以为两个链表的内存地址是一致的 var newPerson new Chinese { Name 麻子 }; //向新链表中添加元素 MachinePositionList.Add(newPerson); //原链表长度不变 var count chiPersons.Count; //同理删除新链表的元素原链表长度也不变 var zhangSan MachinePositionList[0]; MachinePositionList.Remove(zhangSan); count chiPersons.Count;1. 内存结构图栈内存 堆内存 ───────────────────────────────────────────────────── chiPersons变量 ──→ ListChinese 对象 ├─ 数组元素是引用 ├─ [0] ──→ Chinese对象A (张三,25) ├─ [1] ──→ Chinese对象B (李四,30) └─ [2] ──→ Chinese对象C (王五,28) MachinePositionList变量 ──→ ObservableCollectionChinese 对象 ├─ 内部容器元素是引用 ├─ [0] ──→ 同上Chinese对象A ⬅ 共享 ├─ [1] ──→ 同上Chinese对象B ⬅ 共享 └─ [2] ──→ 同上Chinese对象C ⬅ 共享2. 关键内存行为① 构造函数填充浅拷贝csharpnew ObservableCollectionChinese(chiPersons)只复制了引用指针没有复制Chinese对象本身两个集合的每个槽位指向堆上同一组Chinese对象② 修改元素属性csharpMachinePositionList[0].Age 100;通过MachinePositionList[0]拿到引用顺着指针找到堆上的Chinese对象 A修改其Age字段chiPersons[0].Age也变成 100因为是同一个对象③ 添加新元素csharpMachinePositionList.Add(newPerson);newPerson指向新创建的Chinese对象 D麻子ObservableCollection在自己的内部数组末尾添加这个新引用ListChinese的内部数组长度不变仍为 3两个集合从此独立各自维护自己的引用数组3. 内存变化时序操作chiPersons内部数组MachinePositionList内部数组堆上对象初始化[refA, refB, refC][refA, refB, refC]A, B, C修改Age[refA, refB, refC][refA, refB, refC]A(age100), B, CAdd新元素[refA, refB, refC][refA, refB, refC, refD]A, B, C, D补充var test new ListActionNodeBase { new LevelingActionNode { Id 1 }, new LevelingActionNode { Id 2 }, }; //ActionNodeBase a null; var a test[0]; a new AskForConfirmActionNode(); var b test[0];此时b还是LevelingActionNodea test[0]; // 复制引用a 指向 test[0] 指向的对象 a new ...; // 改变 a 指向a 指向新对象不影响 test[0]