c# 几种深拷贝方式的比较
public static class Tools { //利用 BinaryFormatter 实现深拷贝 public static T DeepCopyByBinary<T>(this T obj) { T t = default(T); IFormatter formatter = new BinaryFormatter(); using (MemoryStream ms = new MemoryStream()) { formatter.Serialize(ms, obj); ms.Seek(0, SeekOrigin.Begin); t = (T)formatter.Deserialize(ms); } return t; } //利用 XmlSerializer 实现深拷贝 public static T DeepCopyByXml<T>(this T obj) { T t = default(T); XmlSerializer xmlserialize = new XmlSerializer(typeof(T)); using (MemoryStream ms = new MemoryStream()) { xmlserialize.Serialize(ms, obj); ms.Seek(0, SeekOrigin.Begin); t = (T)xmlserialize.Deserialize(ms); } return t; } //利用反射实现深拷贝 public static T DeepCopyByReflection<T>(this T tSource) { T tResult = Activator.CreateInstance<T>(); Type sourceType = typeof(T); Type resultType = typeof(T); var sourcePros = sourceType.GetProperties(); foreach (var pro in sourcePros) { var sourceProValue = pro.GetValue(tSource); var resultPro = resultType.GetProperty(pro.Name); resultPro.SetValue(tResult, sourceProValue); } return tResult; } }
Person p1 = new Person { Id = 1, Name = "wjire" }; Stopwatch sw1 = new Stopwatch(); sw1.Start(); for (int i = 0; i < 100000; i++) { Person p2 = p1.DeepCopyByBinary(); } sw1.Stop(); Console.WriteLine($"DeepCopyByBinary 共耗时 {sw1.ElapsedMilliseconds} 毫秒"); Stopwatch sw2 = new Stopwatch(); sw2.Start(); for (int i = 0; i < 100000; i++) { Person p2 = p1.DeepCopyByXml(); } sw2.Stop(); Console.WriteLine($"DeepCopyByXml 共耗时 {sw2.ElapsedMilliseconds} 毫秒"); Stopwatch sw3 = new Stopwatch(); sw3.Start(); for (int i = 0; i < 100000; i++) { Person p2 = p1.DeepCopyByReflection(); } sw3.Stop(); Console.WriteLine($"DeepCopyByReflection 共耗时 {sw3.ElapsedMilliseconds} 毫秒"); //利用 json.net 实现深拷贝 Stopwatch sw4 = new Stopwatch(); sw4.Start(); for (int i = 0; i < 100000; i++) { Person p2 = JsonConvert.DeserializeObject<Person>(JsonConvert.SerializeObject(p1)); } sw4.Stop(); Console.WriteLine($"Newtonsoft.Json 共耗时 {sw4.ElapsedMilliseconds} 毫秒");
运行结果:
反射最快!!
class Program { static void Main(string[] args) { Person p1 = new Person(123) { Id = 1, Age = 33, Name = "wjire" }; Expression<Func<Person, Person>> exp1 = p => new Person(333) { Id = p.Id, Name = p.Name, Age = p.Age }; var func1 = exp1.Compile(); Person p23 = func1(p1); Console.WriteLine(p23.Id); Console.WriteLine("*****************************"); ParameterExpression parameterExpression = Expression.Parameter(p1.GetType(), "p"); // 创造了 lambda表达式中的入参: p Console.WriteLine(parameterExpression); List<MemberBinding> memberBindingList = new List<MemberBinding>(); foreach (PropertyInfo pro in p1.GetType().GetProperties()) { if (!pro.CanWrite) { continue; } MemberExpression property = Expression.Property(parameterExpression, pro.Name); Console.WriteLine(property);// p.Id,p.Name,p.Age MemberBinding memberBinding = Expression.Bind(pro, property); Console.WriteLine(memberBinding);// p=p.Id,p=p.Name,p=p.Age memberBindingList.Add(memberBinding); } var rr = Expression.New(p1.GetType().GetConstructor(new Type[] { typeof(int) }), Expression.Constant(default(int))); MemberInitExpression initExpression = Expression.MemberInit(rr, memberBindingList); Console.WriteLine(initExpression);// new Person { Id = p.Id, Name = p.Name, Age = p.Age } Expression<Func<Person, Person>> exp = Expression.Lambda<Func<Person, Person>>(initExpression, parameterExpression); Console.WriteLine(exp);// p => new Person { Id = p.Id, Name = p.Name, Age = p.Age } Func<Person, Person> func = exp.Compile(); Person p2 = func(p1); Console.WriteLine(p2.Name); Console.WriteLine(p2.Id); Console.WriteLine(p2.Age); Console.ReadKey(); } } internal class Person { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public Person(int id) { this.Id = id; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix