- A+
所属分类:.NET技术
先上结论
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); } } }