对象(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,一经查实,立即删除!

相关文章

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;是个非常值得思考的…

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…

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…

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;拼多多的迅速崛起 我们先看看拼多多这几年的成长历程&…

KestrelServer详解[2]: 网络连接是如何创建的?

《KestrelServer详解[1]&#xff1a;注册监听终结点&#xff08;Endpoint&#xff09;》已经详细讲述了如何使用KestrelServer&#xff0c;现在我们来简单聊聊这种服务器的总体设计和实现原理。当KestrelServer启动的时候&#xff0c;注册的每个终结点将转换成对应的“连接监听…

支付宝支付开发流程

支付宝开发流程1、首先我们先谈谈第三方支付所谓第三方支付就是和一些各大银行签约&#xff0c;并具备一定实力和信誉保障的第三方独立机构提供的交易平台目前市面上常见的有支付宝&#xff0c;财付通&#xff0c;网银&#xff0c;易宝支付等&#xff0c;网站需要实现第三方支付…

MQ消息队列之MSMQ

主要参考文章&#xff1a; 消息队列&#xff08;Message Queue&#xff09;简介及其使用 转载于:https://www.cnblogs.com/mailaidedt/p/6599130.html

css选择器总结

一.选择器 1. css1选择器 2.css2选择器 3.css3选择器 4.:nth-of-type(n)和:nth-child(n)区别 (1).在不指定类型时&#xff0c;nth-child(n)选中的是父元素下的第N个子元素。nth-of-type(n)选中的是父元素下的不同类型标签的第N个。(2).在指定具体元素时,ele:nth-child(n)要求不…

Hypercrx:开源项目不只有Star

01战队简介大家好&#xff0c;我们是Hypercrx战队&#xff0c;非常荣幸获得了首届Microsoft Edge浏览器开拓者大赛的一等奖&#xff01;我是队长唐烨男&#xff08;中&#xff09;&#xff0c;位于我左侧的是宁志成&#xff0c;右侧的是林以任&#xff0c;我们都来自华东师范大…

PHP上传图片到数据库,并进行显示

1、创建数据表 CREATE TABLE ccs_image (id int(4) unsigned NOT NULL auto_increment,description varchar(250) default NULL,bin_data longblob,filename varchar(50) default NULL,filesize varchar(50) default NULL,filetype varchar(50) default NULL,PRIMARY KEY (id)…

.NET 反向代理-YARP

什么是 YARPYARP (另一个反向代理) 设计为一个库&#xff0c;提供核心代理功能&#xff0c;你可以根据应用程序的特定需求进行自定义。YARP 是使用 .NET的基础架构构建在 .NET上的。YARP 的主要不同之处在于&#xff0c;它被设计成可以通过 .NET 代码轻松定制和调整&#xff0c…

JavaScript 开发的45个经典技巧

2019独角兽企业重金招聘Python工程师标准>>> 前言&#xff1a;此篇译文在各网站均有标注原创的声明&#xff0c;译者名字已不可考&#xff0c;暂为佚名 JavaScript是一个绝冠全球的编程语言&#xff0c;可用于Web开发、移动应用开发&#xff08;PhoneGap、Appcelera…