




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第C#深拷貝方法探究及性能比較(多種深拷貝)目錄1、手寫創(chuàng)建對(duì)象2、反射3、Json字符串序列化4、對(duì)象二進(jìn)制序列化5、AutoMapper6、表達(dá)式樹之前學(xué)習(xí)了設(shè)計(jì)模式原型模式,在原型模式中就提到了對(duì)象的深拷貝。深拷貝指的是拷貝一個(gè)對(duì)象時(shí),不僅僅把對(duì)象的引用進(jìn)行復(fù)制,還把該對(duì)象引用的值也一起拷貝。與淺拷貝不同的就是,深拷貝后的拷貝對(duì)象就和源對(duì)象互相獨(dú)立,其中任何一個(gè)對(duì)象的改動(dòng)都不會(huì)對(duì)另外一個(gè)對(duì)象造成影響。
在查詢資料之后,探究了以下幾種C#對(duì)象深拷貝方式,同時(shí)簡(jiǎn)單對(duì)比了以下列出的幾種深拷貝方式的速度(簡(jiǎn)單測(cè)試,僅測(cè)試對(duì)象深拷貝速度,不考慮性能影響)。
測(cè)試平臺(tái):Intel9700K+DDR4360032G,框架為.NET5.0。測(cè)試方式為創(chuàng)建100萬次,比較執(zhí)行時(shí)間。拷貝的對(duì)象如下:
[Serializable]
classUserInfo
publicstringName{get;set;}
publicstringUserId{get;set;}
publicintAge{get;set;}
publicstringAddress{get;set;}
publiclongUpdateTime{get;set;}
publiclongCreateTime{get;set;}
}
1、手寫創(chuàng)建對(duì)象
簡(jiǎn)單對(duì)象創(chuàng)建,不考慮有構(gòu)造函數(shù)的情況。
NewUserInfonewInfo=newNewUserInfo()
Name=info.Name,
Age=info.Age,
UserId=info.UserId,
Address=info.Address,
UpdateTime=info.UpdateTime,
CreateTime=info.CreateTime,
};
100萬次執(zhí)行時(shí)間為39.4073ms,位居第一。當(dāng)然,在這種不考慮構(gòu)造函數(shù)的情況下,手寫創(chuàng)建肯定是最快的。但是同時(shí),如果遇到復(fù)雜對(duì)象,代碼量也是最多的。
2、反射
這也是在日常代碼中最常用的方式之一。
privatestaticTOutTransReflectionTIn,TOut(TIntIn)
TOuttOut=Activator.CreateInstanceTOut
vartInType=tIn.GetType();
foreach(varitemOutintOut.GetType().GetProperties())
varitemIn=tInType.GetProperty(itemOut.Name);;
if(itemIn!=null)
itemOut.SetValue(tOut,itemIn.GetValue(tIn));
returntOut;
}
調(diào)用
NewUserInfonewInfo=TransReflectionUserInfo,NewUserInfo(info);
100萬次執(zhí)行時(shí)間為1618.4662ms,平均執(zhí)行時(shí)間為0.001618,看起來還行。
3、Json字符串序列化
使用System.Text.Json作為序列化和反序列化工具。
UserInfonewInfo=JsonSerializer.DeserializeUserInfo(JsonSerializer.Serialize(info));
100萬次執(zhí)行時(shí)間為2222.2078ms,比反射慢一點(diǎn)點(diǎn)。
4、對(duì)象二進(jìn)制序列化
首先不推薦使用這種方式,一是BinaryFormatter.Serialize微軟已不推薦使用(據(jù)微軟官網(wǎng)文檔說是有漏洞,具體有什么漏洞沒細(xì)究),二是必須在要序列化的對(duì)象上面寫上Serializable的關(guān)鍵字,三是速度并不理想。
privatestaticTOutObjectMemoryConvertTIn,TOut(TIntIn)
using(MemoryStreamms=newMemoryStream())
BinaryFormatterformatter=newBinaryFormatter();
formatter.Serialize(ms,tIn);
ms.Position=0;
return(TOut)formatter.Deserialize(ms);
}
100萬次執(zhí)行時(shí)間為8545.9835ms,講道理應(yīng)該是比Json序列化要更快的,但是實(shí)際上慢了許多。
5、AutoMapper
熟悉的AutoMapper,性能也沒有讓我們失望。
//循環(huán)外創(chuàng)建MapperConfig
varconfig=newMapperConfiguration(cfg=cfg.CreateMapUserInfo,UserInfo
varmapper=config.CreateMapper();
//循環(huán)內(nèi)調(diào)用
UserInfonewInfo=mapper.MapUserInfo(info);
100萬次執(zhí)行時(shí)間為267.5073ms,位居第三。
6、表達(dá)式樹
重頭戲來了,此處代碼來源于文首中的博客中,性能讓人大吃一驚。其原理是反射和表達(dá)式樹相結(jié)合,先用反射獲取字段然后緩存起來,再用表達(dá)式樹賦值。
publicstaticclassTransExpTIn,TOut
privatestaticreadonlyFuncTIn,TOutcache=GetFunc();
privatestaticFuncTIn,TOutGetFunc()
ParameterExpressionparameterExpression=Expression.Parameter(typeof(TIn),"p");
ListMemberBindingmemberBindingList=newListMemberBinding
foreach(varitemintypeof(TOut).GetProperties())
if(!item.CanWrite)continue;
MemberExpressionproperty=Expression.Property(parameterExpression,typeof(TIn).GetProperty(item.Name));
MemberBindingmemberBinding=Expression.Bind(item,property);
memberBindingList.Add(memberBinding);
MemberInitExpressionmemberInitExpression=Expression.MemberInit(Expression.New(typeof(TOut)),memberBindingList.ToArray());
ExpressionFuncTIn,TOutlambda=Expression.LambdaFuncTIn,TOut(memberInitExpression,newParameterExpression[]{parameterExpression});
returnlambda.Compile();
publicstaticTOutTrans(TIntIn)
returncache(tIn);
}
調(diào)用
UserInfonewInfo=TransExpUserInfo,UserInfo.Trans(info);
100萬次執(zhí)行時(shí)間為77.3653ms,位居第二。僅比手寫慢一點(diǎn)點(diǎn)。
簡(jiǎn)單整理成柱狀圖,可以很清晰的對(duì)比出這幾種深拷貝方式之間的速度差距??偨Y(jié)來說就是,一般簡(jiǎn)單的對(duì)象深拷貝,推薦直接手寫,復(fù)雜對(duì)象深拷貝,推薦使用表達(dá)式樹。當(dāng)然,如果創(chuàng)建對(duì)象中還涉及到構(gòu)造函數(shù)初始化,那又是不同的情況,這里暫不討論。
附上本次測(cè)試用的完整代碼。
usingAutoMapper;
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Diagnostics;
usingSystem.IO;
usingSystem.Linq.Expressions;
usingSystem.Runtime.Serialization;
usingSystem.Runtime.Serialization.Formatters.Binary;
usingSystem.Text.Json;
usingSystem.Threading.Tasks;
namespaceTestObjectDeepCopy
classProgram
staticvoidMain(string[]args)
UserInfoinfo=newUserInfo()
Name="張三",
Age=18,
UserId=Guid.NewGuid().ToString("N"),
Address="銀河系地球中國(guó)",
UpdateTime=1615888888,
CreateTime=1615895454,
varconfig=newMapperConfiguration(cfg=cfg.CreateMapUserInfo,UserInfo
varmapper=config.CreateMapper();
intcount=1000000;
Stopwatchsw=newStopwatch();
sw.Start();
for(inti=-0;icount;i++)
//手寫39.4073ms
//UserInfonewInfo=newUserInfo()
//Name=info.Name,
//Age=info.Age,
//UserId=info.UserId,
//Address=info.Address,
//UpdateTime=info.UpdateTime,
//CreateTime=info.CreateTime,
//};
//反射1618.4662ms
//UserInfonewInfo=TransReflectionUserInfo,UserInfo(info);
//Json字符串序列化2222.2078ms
//UserInfonewInfo=JsonSerializer.DeserializeUserInfo(JsonSerializer.Serialize(info));
//對(duì)象二進(jìn)制序列化8545.9835ms
//UserInfonewInfo=ObjectMemoryConvertUserInfo,UserInfo(info);
//表達(dá)式樹77.3653ms
//UserInfonewInfo=TransExpUserInfo,UserInfo.Trans(info);
//AutoMapper267.5073ms
//UserInfonewInfo=mapper.MapUserInfo(info);
Console.WriteLine("總共花費(fèi){0}ms.",sw.Elapsed.TotalMilliseconds);
sw.Stop();
Console.ReadKey();
privatestaticTOutTransReflectionTIn,TOut(TIntIn)
TOuttOut=Activator.CreateInstanceTOut
vartInType=tIn.GetType();
foreach(varitemOutintOut.GetType().GetProperties())
varitemIn=tInType.GetProperty(itemOut.Name);;
if(itemIn!=null)
itemOut.SetValue(tOut,itemIn.GetValue(tIn));
returntOut;
privatestaticTOutObjectMemoryConvertTIn,TOut(TIntIn)
using(MemoryStreamms=newMemoryStream())
BinaryFormatterformatter=newBinaryFormatter();
formatter.Serialize(ms,tIn);
ms.Position=0;
return(TOut)formatter.Deserialize(ms);
publicstaticclassTransExpTIn,TOut
privatestaticreadonlyFuncTIn,TOutcache=GetFunc();
privatestaticFuncTIn,TOutGetFunc()
ParameterExpressionparameterExpression=Expression.Parameter(typeof(TIn),"p");
ListMemberBindingmemberBindingList=newListMemberBinding
foreach(varitemintypeof(TOut).GetProperties())
if(!item.CanWrite)continue;
MemberExpressionproperty=Expression.Property(parameterExpression,typeof(TIn).GetProperty(item.Name));
MemberBindingmemberBindin
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 工程介紹居間服務(wù)合同
- 進(jìn)口車免稅合同協(xié)議
- 水務(wù)安全協(xié)議書
- 產(chǎn)品售后服務(wù)與保修條款協(xié)議
- 區(qū)域總代理協(xié)議合同
- 《胸部損傷病人護(hù)理》課件
- 都蘭縣糧油購(gòu)銷合同協(xié)議
- 互聯(lián)網(wǎng)+電子法律服務(wù)協(xié)議
- 住宅小區(qū)物業(yè)管理服務(wù)合同
- 超市門店設(shè)計(jì)合同協(xié)議
- 幕墻UHPC施工專項(xiàng)方案 (評(píng)審版)
- 2025年中建四局土木工程有限公司招聘筆試參考題庫(kù)含答案解析
- 創(chuàng)新設(shè)計(jì)前沿知到智慧樹章節(jié)測(cè)試課后答案2024年秋浙江大學(xué)
- 2025年高考生物復(fù)習(xí)新題速遞之基因工程(2024年9月)
- 小型手推式除雪機(jī)畢業(yè)設(shè)計(jì)說明書(有全套CAD圖)
- 【數(shù) 學(xué)】同底數(shù)冪的乘法課件 2024-2025學(xué)年北師大版七年級(jí)數(shù)學(xué)下冊(cè)
- 地鐵導(dǎo)向標(biāo)識(shí)安裝施工方案
- 數(shù)據(jù)科學(xué)與大數(shù)據(jù)技術(shù)《畢業(yè)實(shí)習(xí)》 課程教學(xué)大綱
- 政務(wù)新媒體管理培訓(xùn)
- 2024年湖北省武漢市中考英語真題(含解析)
- 2024年國(guó)家公務(wù)員考試《行測(cè)》真題卷(副省級(jí))答案及解析
評(píng)論
0/150
提交評(píng)論