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

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第C#深拷貝方法探究及性能比較(多種深拷貝)目錄1、手寫創(chuàng)建對象2、反射3、Json字符串序列化4、對象二進制序列化5、AutoMapper6、表達式樹之前學習了設計模式原型模式,在原型模式中就提到了對象的深拷貝。深拷貝指的是拷貝一個對象時,不僅僅把對象的引用進行復制,還把該對象引用的值也一起拷貝。與淺拷貝不同的就是,深拷貝后的拷貝對象就和源對象互相獨立,其中任何一個對象的改動都不會對另外一個對象造成影響。

在查詢資料之后,探究了以下幾種C#對象深拷貝方式,同時簡單對比了以下列出的幾種深拷貝方式的速度(簡單測試,僅測試對象深拷貝速度,不考慮性能影響)。

測試平臺:Intel9700K+DDR4360032G,框架為.NET5.0。測試方式為創(chuàng)建100萬次,比較執(zhí)行時間??截惖膶ο笕缦拢?/p>

[Serializable]

classUserInfo

publicstringName{get;set;}

publicstringUserId{get;set;}

publicintAge{get;set;}

publicstringAddress{get;set;}

publiclongUpdateTime{get;set;}

publiclongCreateTime{get;set;}

}

1、手寫創(chuàng)建對象

簡單對象創(chuàng)建,不考慮有構造函數(shù)的情況。

NewUserInfonewInfo=newNewUserInfo()

Name=info.Name,

Age=info.Age,

UserId=info.UserId,

Address=info.Address,

UpdateTime=info.UpdateTime,

CreateTime=info.CreateTime,

};

100萬次執(zhí)行時間為39.4073ms,位居第一。當然,在這種不考慮構造函數(shù)的情況下,手寫創(chuàng)建肯定是最快的。但是同時,如果遇到復雜對象,代碼量也是最多的。

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;

}

調用

NewUserInfonewInfo=TransReflectionUserInfo,NewUserInfo(info);

100萬次執(zhí)行時間為1618.4662ms,平均執(zhí)行時間為0.001618,看起來還行。

3、Json字符串序列化

使用System.Text.Json作為序列化和反序列化工具。

UserInfonewInfo=JsonSerializer.DeserializeUserInfo(JsonSerializer.Serialize(info));

100萬次執(zhí)行時間為2222.2078ms,比反射慢一點點。

4、對象二進制序列化

首先不推薦使用這種方式,一是BinaryFormatter.Serialize微軟已不推薦使用(據(jù)微軟官網(wǎng)文檔說是有漏洞,具體有什么漏洞沒細究),二是必須在要序列化的對象上面寫上Serializable的關鍵字,三是速度并不理想。

privatestaticTOutObjectMemoryConvertTIn,TOut(TIntIn)

using(MemoryStreamms=newMemoryStream())

BinaryFormatterformatter=newBinaryFormatter();

formatter.Serialize(ms,tIn);

ms.Position=0;

return(TOut)formatter.Deserialize(ms);

}

100萬次執(zhí)行時間為8545.9835ms,講道理應該是比Json序列化要更快的,但是實際上慢了許多。

5、AutoMapper

熟悉的AutoMapper,性能也沒有讓我們失望。

//循環(huán)外創(chuàng)建MapperConfig

varconfig=newMapperConfiguration(cfg=cfg.CreateMapUserInfo,UserInfo

varmapper=config.CreateMapper();

//循環(huán)內調用

UserInfonewInfo=mapper.MapUserInfo(info);

100萬次執(zhí)行時間為267.5073ms,位居第三。

6、表達式樹

重頭戲來了,此處代碼來源于文首中的博客中,性能讓人大吃一驚。其原理是反射和表達式樹相結合,先用反射獲取字段然后緩存起來,再用表達式樹賦值。

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);

}

調用

UserInfonewInfo=TransExpUserInfo,UserInfo.Trans(info);

100萬次執(zhí)行時間為77.3653ms,位居第二。僅比手寫慢一點點。

簡單整理成柱狀圖,可以很清晰的對比出這幾種深拷貝方式之間的速度差距??偨Y來說就是,一般簡單的對象深拷貝,推薦直接手寫,復雜對象深拷貝,推薦使用表達式樹。當然,如果創(chuàng)建對象中還涉及到構造函數(shù)初始化,那又是不同的情況,這里暫不討論。

附上本次測試用的完整代碼。

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="銀河系地球中國",

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));

//對象二進制序列化8545.9835ms

//UserInfonewInfo=ObjectMemoryConvertUserInfo,UserInfo(info);

//表達式樹77.3653ms

//UserInfonewInfo=TransExpUserInfo,UserInfo.Trans(info);

//AutoMapper267.5073ms

//UserInfonewInfo=mapper.MapUserInfo(info);

Console.WriteLine("總共花費{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等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論