为什么该C#示例中的所有List<int>列表都被意外修改?
异常行为根本原因
C#中List<T>属于引用类型,变量存储的是堆中实际列表对象的内存地址,而非列表本身的数据,你代码中所有列表变量实际指向同一个堆对象,修改时自然会全局同步:
- 构造函数中执行
numbers = _numbers时,没有拷贝传入的列表数据,只是把外部someDate的地址赋值给了numbers字段,二者指向同一个列表 GetNumbers方法中List<int> localNumbers = numbers同样是地址赋值,localNumbers也和numbers共享同一个列表对象- 循环修改
localNumbers的元素时,本质是修改堆中的唯一列表对象,同时会同步到someDate、numbers、diffrentNum三个变量,最终所有变量读取到的都是修改后的值。
修复方案
只要在需要独立存储的地方做列表的浅拷贝(因为元素是int值类型,浅拷贝即可实现数据隔离):
修正后的MyClass代码
public class MyClass { public List<int> numbers { get; } public List<int> diffrentNum { get; set; } public MyClass(List<int> _numbers) { // 拷贝传入的列表,生成独立的原始数据副本 numbers = new List<int>(_numbers); diffrentNum = GetNumbers(); } private List<int> GetNumbers() { // 拷贝原始列表,修改副本不影响原始数据 List<int> localNumbers = new List<int>(numbers); // 原代码写了i<localNumbers.Count-1会跳过最后一位元素,需要全量修改可去掉-1 for (int i=0;i<localNumbers.Count-1;i++) { if (localNumbers[i] > 0) { localNumbers[i]--; } } return localNumbers; } }
内容的提问来源于stack exchange,提问作者JohnyCage1948
相关产品推荐
相关产品推荐

