C#深拷貝方法探究及性能比較(多種深拷貝)_第1頁
C#深拷貝方法探究及性能比較(多種深拷貝)_第2頁
C#深拷貝方法探究及性能比較(多種深拷貝)_第3頁
C#深拷貝方法探究及性能比較(多種深拷貝)_第4頁
C#深拷貝方法探究及性能比較(多種深拷貝)_第5頁
已閱讀5頁,還剩4頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論