C# .NET 常见DeepCopy 深度拷贝的性能对比

  • C# .NET 常见DeepCopy 深度拷贝的性能对比已关闭评论
  • 161 次浏览
  • A+
所属分类:.NET技术
摘要

先上结论由测试得出结论:
1 首选Expression表达式树,性能大幅领先于反射,耗时仅为反射的1/70
2 反射,最常用的深度拷贝方法,书写比较简单
3 JSONConvert,最简答的写法,适用于偶尔需要深度拷贝的时候使用
4 BinaryFormatter,不推荐,需要在类上加上序列化声明,并且在.NET 5.0中该方法已经被微软声明为过期.

先上结论

Method Mean Error StdDev Gen0 Gen1 Allocated
JSONConvert 2,273.02 ns 43.758 ns 52.091 ns 0.6599 - 4160 B
Reflection 1,009.13 ns 10.110 ns 8.442 ns 0.0629 - 400 B
BinaryFormatter 8,146.04 ns 85.914 ns 67.076 ns 1.6022 0.0153 10088 B
Expression 14.70 ns 0.315 ns 0.430 ns 0.0063 - 40 B

由测试得出结论:
1 首选Expression表达式树,性能大幅领先于反射,耗时仅为反射的1/70
2 反射,最常用的深度拷贝方法,书写比较简单
3 JSONConvert,最简答的写法,适用于偶尔需要深度拷贝的时候使用
4 BinaryFormatter,不推荐,需要在类上加上序列化声明,并且在.NET 5.0中该方法已经被微软声明为过期.

代码

 public static class DeepCopyUtil     {         /// <summary>         /// Json深度拷贝         /// </summary>         /// <typeparam name="T"></typeparam>         /// <param name="obj"></param>         /// <returns></returns>         public static T DeepCopyJson<T>(T obj)         {             return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(obj));         }          /// <summary>         /// 反射深度拷贝         /// </summary>         /// <typeparam name="T"></typeparam>         /// <param name="obj"></param>         /// <returns></returns>         public static T DeepCopyReflection<T>(T obj)         {             var type = obj.GetType();             object o = Activator.CreateInstance(type);             System.Reflection.PropertyInfo[] PI = type.GetProperties();             for (int i = 0; i < PI.Count(); i++)             {                 System.Reflection.PropertyInfo P = PI[i];                 P.SetValue(o, P.GetValue(obj));             }             return (T)o;         }           public static T DeepCopyMemory<T>(T obj)         {             object retval;             using (MemoryStream ms = new MemoryStream())             {                 BinaryFormatter bf = new BinaryFormatter();                 //序列化成流                 bf.Serialize(ms, obj);                 ms.Seek(0, SeekOrigin.Begin);                 //反序列化成对象                 retval = bf.Deserialize(ms);                 ms.Close();             }             return (T)retval;         }          public static class TransExp<TIn, TOut>         {             private static readonly Func<TIn, TOut> cache = GetFunc();             private static Func<TIn, TOut> GetFunc()             {                 ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");                 List<MemberBinding> memberBindingList = new List<MemberBinding>();                  foreach (var item in typeof(TOut).GetProperties())                 {                     if (!item.CanWrite) continue;                     MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));                     MemberBinding memberBinding = Expression.Bind(item, property);                     memberBindingList.Add(memberBinding);                 }                  MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());                 Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[] { parameterExpression });                  return lambda.Compile();             }              public static TOut Trans(TIn tIn)             {                 return cache(tIn);             }         }     }