在 .NET 中实现深拷贝(Deep Copy)有几种常用方法,深拷贝是指创建一个新对象,并递归地复制原对象及其所有引用对象,而不仅仅是复制引用。
目录
- 1. 使用序列化/反序列化
- 2. 使用 JSON 序列化(Newtonsoft.Json 或 System.Text.Json)
- 3. 实现 ICloneable 接口(手动实现)
- 4. 使用 AutoMapper(适用于复杂对象)
- 5. 注意事项
- 6. 推荐方法
1. 使用序列化/反序列化
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;public static class ObjectCopier
{public static T DeepCopy<T>(T obj){if (!typeof(T).IsSerializable){throw new ArgumentException("The type must be serializable.", nameof(obj));}if (ReferenceEquals(obj, null)){return default;}IFormatter formatter = new BinaryFormatter();using (var stream = new MemoryStream()){formatter.Serialize(stream, obj);stream.Seek(0, SeekOrigin.Begin);return (T)formatter.Deserialize(stream);}}
}
2. 使用 JSON 序列化(Newtonsoft.Json 或 System.Text.Json)
// 使用 Newtonsoft.Json
using Newtonsoft.Json;public static T DeepCopy<T>(T obj)
{var json = JsonConvert.SerializeObject(obj);return JsonConvert.DeserializeObject<T>(json);
}// 使用 System.Text.Json (推荐.NET Core 3.0+)
using System.Text.Json;public static T DeepCopy<T>(T obj)
{var json = JsonSerializer.Serialize(obj);return JsonSerializer.Deserialize<T>(json);
}
3. 实现 ICloneable 接口(手动实现)
public class MyClass : ICloneable
{public int Value { get; set; }public MyOtherClass Other { get; set; }public object Clone(){var copy = (MyClass)MemberwiseClone(); // 浅拷贝copy.Other = (MyOtherClass)Other.Clone(); // 深拷贝引用类型return copy;}
}public class MyOtherClass : ICloneable
{public string Name { get; set; }public object Clone(){return MemberwiseClone(); // 浅拷贝(因为只有值类型)}
}
4. 使用 AutoMapper(适用于复杂对象)
using AutoMapper;var config = new MapperConfiguration(cfg =>
{cfg.CreateMap<MyClass, MyClass>();cfg.CreateMap<MyOtherClass, MyOtherClass>();
});var mapper = config.CreateMapper();
var copy = mapper.Map<MyClass>(original);
5. 注意事项
- 序列化方法要求所有相关类都是可序列化的(有
[Serializable]
特性或可以被 JSON 序列化) - 循环引用可能导致堆栈溢出或序列化异常
- 性能考虑:对于大型对象图,序列化方法可能较慢
- 某些特殊类型(如委托、COM 对象)可能无法正确拷贝
6. 推荐方法
- 对于简单对象:使用 JSON 序列化(System.Text.Json 性能较好)
- 对于复杂对象图:考虑实现 ICloneable 或使用 AutoMapper
- 对于性能敏感场景:考虑手动实现深拷贝逻辑
选择哪种方法取决于具体需求、对象复杂度和性能要求。