C#中如何深拷贝字典值,避免修改取出对象时影响原字典内容
现象原因
你遇到的同步修改问题是C#引用类型的默认特性导致的:Employee为类(引用类型)时,字典中存储的不是对象实体,而是对象在托管堆中的内存引用。你通过dict[1]取出的employee变量和字典内存储的引用指向同一个堆对象,修改属性自然会同步变更字典中对应的对象值。
解决方法
你可以通过拷贝对象的方式切断引用关联,常用实现方案如下:
- 方案1:给
Employee类实现拷贝方法
可以实现ICloneable接口,或者自定义浅/深拷贝方法,示例代码如下:
取值时调用拷贝方法即可:public class Employee : ICloneable { public string Name { get; set; } public int Id { get; set; } // 其他属性 // 浅拷贝:仅复制值类型属性和字符串,嵌套引用类型仍会共享引用 public object Clone() { return this.MemberwiseClone(); } // 深拷贝:如果存在嵌套引用类型属性,需要逐层复制所有层级的对象 public Employee DeepClone() { return new Employee { Name = this.Name, Id = this.Id // 若有嵌套引用类型,此处需要对应做拷贝,例:Department = this.Department.DeepClone() }; } }// 调用浅拷贝 var employee = (Employee)dict[1].Clone(); // 或调用深拷贝 // var employee = dict[1].DeepClone(); employee.Name = "Changed"; // 此时修改不会影响字典内的原对象 - 方案2:轻量场景下将
Employee改为值类型(struct)
如果Employee是仅用来承载数据的轻量结构,没有继承等需求,可以直接将类改为结构体:
结构体属于值类型,从字典取值时会自动生成值拷贝,修改新变量不会影响字典内的原始数据。注意该方案适用场景有限,结构体存在装箱拆箱开销、无法继承等限制,仅适合简单数据结构使用public struct Employee { public string Name { get; set; } public int Id { get; set; } } - 方案3:无需修改原类的手动拷贝方式
如果不想改动Employee的原有定义,取值时手动复制属性生成新对象即可:var original = dict[1]; var employee = new Employee { Name = original.Name, Id = original.Id // 其他属性依次赋值 }; employee.Name = "Changed"; // 修改不会同步到原对象
注意:如果
Employee包含嵌套的自定义引用类型属性,仅用浅拷贝仍会出现嵌套属性同步修改的问题,该场景下必须使用深拷贝逐层复制所有引用类型的属性。
内容的提问来源于stack exchange,提问作者Kunal Bathija
相关产品推荐
相关产品推荐

