You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 07:54:02