先上结论

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);
}
}
}

C# .NET 常见DeepCopy 深度拷贝的性能对比的更多相关文章

  1. Python [拷贝copy / 深度拷贝deepcopy] | 可视化理解

    Python 是一门面向对象的语言, 在Python一切皆对象. 每一个对象都有由以下三个属性组成: ------------------------------------------------- ...

  2. lua实现深度拷贝table表

    lua当变量作为函数的参数进行传递时,类似的也是boolean,string,number类型的变量进行值传递.而table,function,userdata类型的变量进行引用传递.故而当table ...

  3. String 类的实现(2)深度拷贝详解

    我们已经知道了浅拷贝存在的问题,即多次析构同一空间.这个问题是类的成员函数引起的,就是前面浅拷贝里相当于编译器自动合成的函数,确切的说,浅拷贝里的问题是由隐士拷贝构造函数和隐士赋值运算符引起的. 拷贝 ...

  4. Python 直接赋值、浅拷贝和深度拷贝全解析

    直接赋值:其实就是对象的引用(别名,其实就是一个人今天叫张三 明天叫张狗子的意思).这个人比较自由单身狗嘛  可以恋爱可以分手  就是一个小屌丝. 浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的 ...

  5. Python 直接赋值、浅拷贝和深度拷贝解析

    直接赋值:其实就是对象的引用(别名). 浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象. 深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象 ...

  6. 图解Python的直接赋值与浅拷贝和深度拷贝三者区别

    直接赋值:其实就是对象的引用(别名). 浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象. 深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象 ...

  7. lua的克隆函数,table的深度拷贝

    --深度拷贝Table function DeepCopy(obj) local InTable = {}; local function Func(obj) if type(obj) ~= &quo ...

  8. Python直接赋值、浅拷贝和深度拷贝解析

    直接赋值:其实就是对象的引用(别名). 浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象. 深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象 ...

  9. java 深度拷贝 复制 深度复制

    1.深度拷贝.复制代码实现 最近需要用到比较两个对象属性的变化,其中一个是oldObj,另外一个是newObj,oldObj是newObj的前一个状态,所以需要在newObj的某个状态时,复制一个一样 ...

  10. python中浅拷贝和深度拷贝的区别

    在很多面试题中都会问到浅拷贝跟深度拷贝的区别,前几天一个朋友也问到了我浅拷贝跟深度拷贝到底有什么区别,这里就简单举栗子讲一下两者的区别. 浅拷贝(copy()):拷贝父对象,不会拷贝对象的内部的子对象 ...

随机推荐

  1. [Gin] gin-jwt 业务逻辑中使用实例化的 middleware 的方式

    依然需要按文档所示实例化一个 authMiddleware. 在路由组中使用的方式是 authMiddleware.MiddlewareFunc(). 通过追踪 MiddlewareFunc 可以知道 ...

  2. dotnet 已知问题 错误标记 MethodImplOptions.InternalCall 特性参数将会在类型访问之前抛出 TypeLoadException 异常

    本文将记录一个 dotnet 的已知问题.当自己不小心在方法上不正确标记了 MethodImplAttribute 特性时,错误选择了 MethodImplOptions.InternalCall 参 ...

  3. 2019-8-31-dotnet-使用-Environment.FailFast-结束程序

    title author date CreateTime categories dotnet 使用 Environment.FailFast 结束程序 lindexi 2019-08-31 16:55 ...

  4. 前端关于获取网络时间的方法api

    淘宝 http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp 苏宁http://quan.suning.com/getSys ...

  5. 一键自动化博客发布工具,用过的人都说好(infoq篇)

    infoq的博客发布界面也是非常简洁的.首页就只有基本的标题,内容和封面图片,所以infoq的实现也相对比较简单. 一起来看看吧. 前提条件 前提条件当然是先下载 blog-auto-publishi ...

  6. .NET6 Minimal API 集成Autofac

    前提 集成Autofac前需要先添加两个依赖包 可以通过 NuGet 进行安装,使用以下命令: dotnet add package Autofac dotnet add package Autofa ...

  7. 5GC 关键技术之 SBA(基于服务的软件架构)

    目录 文章目录 目录 前文列表 5GC 的关键技术 SBA(基于服务的软件架构) 微服务架构 NF 的模块化 NF Service 的服务化 前文列表 <简述移动通信网络的演进之路> &l ...

  8. 虚拟机上k8s部署好的第二天用时总是出现的各种问题

    open /run/flannel/subnet.env: no such file or directory open /run/flannel/subnet.env: no such file o ...

  9. 大数据Hadoop集群的扩容及缩容(动态添加删除节点)

    添加白名单和黑名单 白名单,表示在白名单的主机IP地址可以用来存储数据 企业中:配置白名单,可以尽量防止黑客恶意访问攻击. 配置白名单步骤如下:原文:sw-code 1)在NameNode节点的/op ...

  10. 如何从0-1了解 熟悉 精通gitlab

    加入gitlab团队项目: 打开其他用户极狐邀请邮件: 点击接受紫色邀请按钮"accept invitation": 选择免费试用90天saas服务: 使用邮箱注册进行邮箱验证[验 ...