C# .NET 常见DeepCopy 深度拷贝的性能对比
2023-03-31 10:56:43 时间
先上结论
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);
}
}
}
相关文章
- ASP.net判断上传文件类型的三种方法
- ASP.NET常被忽视的一些细节
- 将死的平台:.Net
- HTTP协议/IIS 原理及ASP.NET运行机制浅析【图解】
- 基于.net开发chrome核心浏览器【一】
- .NET陷阱之奇怪的OutOfMemoryException
- .NET领域驱动设计—初尝(二)
- Visual Studio的工程结构解析
- .NET领域驱动设计—初尝
- HttpContext.Current并非无处不在
- Asp.Net页面生命周期
- ASP.NET WebForm也可以这样用Ajax
- 如何在ASP.NET应用程序中初始化
- AJAX长轮询之DotNet实现
- 减少.NET应用程序内存占用的一则实践
- Visual Studio中编译任务压缩js和CSS文件
- 各种AJAX方法的使用比较
- .NET性能调优之一:ANTS Performance Profiler的使用
- Ajax请求过程中显示进度的简单实现
- 不改代码就能优化ASP.NET网站性能的方法