對象(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.pswp.cn/news/282565.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/282565.shtml
英文地址,請注明出處:http://en.pswp.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…