对象(poco)深度克隆

提供深度克隆对象功能,基于编译表达式实现,性能与原生代码几无差别,远超 json/binary 序列化实现。

1. 简单示例

class Person
{public int Id { get; set; }public string Name { get; set; }public int Age { get; set; }public DateTime Birth { get; set; }public double Score { get; set; }public DateTime CreateTime { get; set; }public DateTime UpdateTime { get; set; }public EnumState State { get; set; }public string Desc { get; set; }public string Phone { get; set; }
}//克隆
var list = new List<Person>(){/*放点数据*/}
var newList = list.DeepClone();

2. 性能

分别与原生代码,json、binary 序列化机制比对;

原生代码如:

var newList = list.Select(i => new Person { Id = i.Id/*其他属性*/}).ToList();
```

json序列化如:

var newList = JsonConvert.DeserializeObject<List<Person>>(JsonConvert.SerializeObject(list));

binary序列化如:

BinaryFormatter bf = new BinaryFormatter();
var stream = new MemoryStream();
bf.Serialize(stream, list); stream.Seek(0, SeekOrigin.Begin);bf.Deserialize(stream);

测试效果如下:

35fc03ac2c99d0235340e7db9cff3ec8.png

测试代码,参考:https://gitee.com/jackletter/DotNetCommon/blob/master/tests/DeepClonePerformanceTest/Program.cs

3. 详细功能

单元测试地址:https://gitee.com/jackletter/DotNetCommon/blob/master/tests/DotNetCommon.Test/Extensions/ObjectTests_DeepClone.cs

3.1 支持的完整数据类型如下:

  • 基础类型 sbyte/byte/short/ushort/int/uint/long/ulong/float/double/decimal bool/enum/char/string

    DateTime/DateTimeOffset/DateOnly/TimeOnly/TimeSpan/Guid

  • pojo、结构体

  • 数组、集合、字典 T[]List<T>Dictionary<TKey, TValue>HashSet<T>LinkedList<T>ReadOnlyCollection<T>

    注意:必须是泛型的且指定具体的类型,而不是 List<object>

  • 元组

    Tuple<T1,... ValueTuple<T1....

  • 匿名类型

    new {Id=1.Name="小明",Teacher=new Teacher()}.DeepClone()

  • JObject/JArray/JToken

  • 已实现 ICloneable 接口的类型

3.2 特点

该克隆方法支持引用关系的拷贝,如:

class Node
{public int Id { get; set; }public Node Parent { get; set; }public List<Node> Children { get; set; }
}
//构造
var node=new Node{ Id = 1, Childrem = new List<Node>()};
var subNode=new Node{ Id = 2, Parent = node };
node.Children.Add(subNode);//深度克隆,不会死循环,引用关系会一并拷贝过来
var newNode = node.DeepClone();
Assert.IsTrue(newNode != node);
Assert.IsTrue(newNode.Children[0].Parent == newNode);

之所以能将引用关系也拷贝过来,是因为内部使用了字典进行缓存,如果明确实例内部没有引用关系的话,可以将它关闭,关闭后性能提升将近一倍。

//关闭克隆时的引用关系
node.DeepClone(false);

4. FAQ

4.1 为什么会支持元组的克隆,元组不是值类型吗?

元组确实是值类型,但里面可以存放 对象引用,如:

(int Id, Teacher teacher) tuple = (1,new Teacher{ Name = "小明"});
var newTuple = tuple.DeepClone(false);
newTuple.teacher.Name+="update";//由于是深拷贝,旧数据并未更改
Assert.IsTrue(tuple.teacher.Name == "小明");

4.2 为什么会支持匿名类型的克隆,匿名类型不是只读的吗?

这个和元组就相似了,虽然匿名类型是只读的,但它里面可以存放对象引用,如:

var obj = new { Id = 1, teacher = new Teacher{ Name = "小明"}};
var newObj = obj.DeepClone(false);
newObj.teacher.Name+="update";

4.3 为什么会支持 ReadOnlyCollection 这不是只读的吗?

一方面,虽然 ReadOnlyCollection 本身只读,但它里面存的对象实例属性是可更改,肯定要拷贝;

另一方面,ReadOnlyCollection 只是对外暴露的接口只读,但没有说它里面的数据集一定不能改,如:

var list = new List<int>{ 1, 2 };
var readList = new ReadOnlyCollection<int>(list);
//readList 此时是只读的,但仍然可以更改 list
list.Add(3);
//readList 也随之被更改
Assert.IsTrue(readList.Count == 3);

4.4 为什么List、Array 都必须是泛型且指定具体的类型?

这是因为,克隆的逻辑是基于编译表达式实现的,相当于在运行时 生成一个函数,在生成这个函数时会分析 List<T> 中的T

如果T 是 Person{ int Id,string Name} 那么生成的函数就是 old=>new Person(){Id=old.Id,Name=old.Name}。

如果是非泛型的 List 或者是 List<object> 那么将不能反射到具体的属性,也就不能生成对应的函数。

4.5 字典 Dictionary<TKey, TValue> 的TKey也会进行克隆吗?

会。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/282565.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php将数字转化为中文大写人民币格式

<?phpfunction cny($ns) {static $cnums array("零","壹","贰","叁","肆","伍","陆","柒","捌","玖"),$cnyunits array("圆","角","分&…

BZOJ1787 [Ahoi2008]Meet 紧急集合 LCA

欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1787 题意概括 有一棵节点为n个(n≤500000)的树。接下来m次询问(m≤500000)&#xff0c;每次给出3个点 a,b,c &#xff0c;现在让你求一个点 p &#xff0c;使得 dis(p,a) dis(p,b) dis(p,c) 最…

Linux之ACL权限控制

ACL权限控制主要目的是提供传统的owner,group,other的read,wirte,execute权限之外的具体权限设置&#xff0c;可以针对单一用户或组来设置特定的权限 设置ACL权限&#xff1a;setfacl查看ACL权限&#xff1a;getfacl 比如&#xff1a;某一目录权限为 drwx------ 2 root root 40…

WIX、Squarespace、WordPress 三者的优劣分别是什么?

层出不穷的智能建站&#xff0c;模板建站&#xff0c;源码建站&#xff0c;云建站&#xff0c;仿站&#xff0c;各种建站概念都抛洒于红海之中。到底什么样的网站适合自己&#xff0c;什么样的网站值得我们去消费&#xff0c;什么样的网站能长久&#xff0c;是个非常值得思考的…

平滑的加权轮询均衡算法

前言在反向代理、路由、分布式应用调度等场景中通常都需要用到负载均衡算法&#xff0c;负载均衡的关键要点是“均衡”&#xff0c;即确保调用请求能均衡地落到多个处理节点上&#xff0c;负载均衡算法一般使用随机或轮询都可以保证均衡性。现实中由于服务器性能或资源分配的差…

php类精确验证身份证号码

<?php class check_IdCard {// $num为身份证号码&#xff0c;$checkSex&#xff1a;1为男&#xff0c;2为女&#xff0c;不输入为不验证public function checkIdentity($num, $checkSex ) { // 不是15位或不是18位都是无效身份证号if (strlen($num) ! 15 && strl…

请说说接口和抽象类的区别?

1.从使用目的来看&#xff1a; 接口只是一个类间的协议&#xff0c;它并没有规定怎么去实现&#xff1b; 抽象类可以重用你代码使你的代码更加简洁&#xff1b;2.从行为来看&#xff1a; 接口可以多继承,multi-implement 抽象类不能实例化&#xff0c;必须子类化才能实例化…

GitHub 使用

Git 是由 Linux 之父 Linus Tovalds 为了更好的管理 linux 内核开发而创立的分布是版本控制/软件管理配置软件. 简单来说, Git 管理你的 代码的历史记录 的工具. 首先注册账户 (已经完成, moveofgod) 然后, 下载一个 GitHub Desktop(mac), msisgit 客户端 (可以用命令行实现, …

LinkedHashMap 与 HashMap区别

2019独角兽企业重金招聘Python工程师标准>>> LinkedHashMap 与 HashMap区别 &#xff08;非原创&#xff09; HashMap,LinkedHashMap,TreeMap都属于Map Map 主要用于存储键(key)值(value)对&#xff0c;根据键得到值&#xff0c;因此键不允许键重复,但允许值重复。 …

C# 11 中的 file local type

C# 11 中的 file local typeIntro在之前的版本中&#xff0c;我们想要一个类型只在当前的类型中生效&#xff0c;通常我们会在一个类的内部声明一个 private 的类型以此来控制这个类型的访问权限&#xff0c;在 C# 11 中引入了一个 file local type&#xff0c;仅在声明类型的这…

PHP实现类似百度搜索自动完成(代码简单)

一、效果图: 二、HTML代码 <html lang"en"> <head><meta charset"utf-8"><title>jQuery UI 自动完成&#xff08;Autocomplete&#xff09; - 默认功能</title><link rel"stylesheet" href"/public/Auto…

Mysql读写分离php脚本

<?php/*php如何连接mysql*/ /*$link mysql_connect(‘localhost‘, ‘root‘, ‘‘);if (!$link) {die(‘Could not connect: ‘ . mysql_error());}echo ‘Connected successfully‘;mysql_close($link);*/ /*php如何选择数据库*//*$link mysql_connect(‘localhost‘, …

CentOS 搭建Postfix+Dovecot简单邮件系统

2019独角兽企业重金招聘Python工程师标准>>> 服务器信息 系统&#xff1a;CentOS 6.5 minimal版本 主机&#xff1a;虚拟机 虚拟机IP&#xff1a;192.168.128.128/24 宿主IP:10.1.79.24/24 安装postfix 注意&#xff1a;CentOS 7实际上已经用postfixSasl2代替sendma…

Js获取当前页面URL各种参数

JS获取当前页面URL各种参数 一&#xff1a;Location Location 对象包含有关当前 URL 的信息。 Location 对象是 Window 对象的一个部分&#xff0c;可通过 window.location 属性来访问。 hash设置或返回从井号 (#) 开始的 URL&#xff08;锚&#xff09;。host设置或返回主机名…

php面试题2018

一 、PHP基础部分 1、PHP语言的一大优势是跨平台&#xff0c;什么是跨平台&#xff1f; PHP的运行环境最优搭配为ApacheMySQLPHP&#xff0c;此运行环境可以在不同操作系统&#xff08;例如windows、Linux等&#xff09;上配置&#xff0c;不受操作系统的限制&#xff0c;所以…

学生党的专属定制福利,你想要的这里全都有!

同学们&#xff1a;您好&#xff01;很⾼兴认识⼤家&#xff01;我是微软的 Regional Cloud Advocate Kinfey Lo&#xff0c;感谢您在课余时间打开这封信。踏⼊⾦秋&#xff0c;技术峰会进⼊了旺季&#xff0c;有⾯向商业的&#xff0c;有⾯向开发者的&#xff0c;有⾯向技术社…

Quartus prime16.0 与modelsim ae 联调

前言 quartus和modelsim联调对仿真还是很方便的&#xff0c;当然最好是quartus干综合到烧录的活&#xff0c;modelsim单独仿真。而且ae版的性能比se版差。 流程&#xff1a; 1.配置modelsim ae路径&#xff1a; 我这里是这个路径&#xff0c;根据你自己安装的地方配置路径。 2.…

30分钟搞定后台登录界面(103个后台PSD源文件、素材网站)

去年八月时要做一个OA系统为了后台界面而烦恼&#xff0c;后来写了一篇博客&#xff08;《后台管理UI的选择》&#xff09;介绍了选择过程与常用后台UI&#xff0c;令我想不到的时竟然有许多开发者与我一样都为这个事情而花费不少时间&#xff0c;最后界面效果还是不佳&#xf…

分析拼多多的崛起【产品思维】

最近朋友圈讨论拼多多上市的新闻大火&#xff0c;各有各的看法&#xff0c;很有意思&#xff0c;突然想起前段时间得到上的《梁宁-产品思维30讲》&#xff0c;所以想从数据和产品角度分析分析拼多多的崛起。 一&#xff1a;拼多多的迅速崛起 我们先看看拼多多这几年的成长历程&…

62、滑动窗口的最大值

一、题目 给定一个数组和滑动窗口的大小&#xff0c;找出所有滑动窗口里数值的最大值。例如&#xff0c;如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3&#xff0c;那么一共存在6个滑动窗口&#xff0c;他们的最大值分别为{4,4,6,6,6,5}&#xff1b; 针对数组{2,3,4,2,6,2,5…