Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the method of deep copy of C #

2025-01-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)05/31 Report--

Today, the editor will share with you the relevant knowledge of what is the method of deep copy of C#. The content is detailed and the logic is clear. I believe most people still know too much about this knowledge, so share this article for your reference. I hope you can get something after reading this article, let's take a look at it.

The test platform is Intel 9700K+DDR4 3600 32G and the framework is .NET 5.0g. The test method is to create 1 million times and compare the execution time. The copied objects are as follows:

[Serializable] class UserInfo {public string Name {get; set;} public string UserId {get; set;} public int Age {get; set;} public string Address {get; set;} public long UpdateTime {get; set;} public long CreateTime {get; set;} 1, handwritten object creation

Simple object creation, regardless of the existence of a constructor.

NewUserInfo newInfo = new NewUserInfo () {Name = info.Name, Age = info.Age, UserId = info.UserId, Address = info.Address, UpdateTime = info.UpdateTime, CreateTime = info.CreateTime,}

The 1 million execution time is 39.4073ms, ranking first. Of course, handwritten creation is certainly the fastest in this case without considering the constructor. But at the same time, if you encounter complex objects, the amount of code is also the largest.

2. Reflection

This is also one of the most common ways in everyday code.

Private static TOut TransReflection (TIn tIn) {TOut tOut = Activator.CreateInstance (); var tInType = tIn.GetType (); foreach (var itemOut in tOut.GetType (). GetProperties ()) {var itemIn = tInType.GetProperty (itemOut.Name);; if (itemIn! = null) {itemOut.SetValue (tOut, itemIn.GetValue (tIn));} return tOut;}

Call

NewUserInfo newInfo = TransReflection (info)

The 1 million execution time is 1618.4662ms, and the average execution time is 0.001618, which looks OK.

3. Json string serialization

Use System.Text.Json as the serialization and deserialization tool.

UserInfo newInfo = JsonSerializer.Deserialize (JsonSerializer.Serialize (info))

The 1 million execution time is 2222.2078ms, which is a little slower than reflection.

4. Object binary serialization

First of all, this method is not recommended, first, BinaryFormatter.Serialize is no longer recommended by Microsoft (according to Microsoft's official website documents, there are loopholes, specific vulnerabilities have not been studied in detail), second, you must write the keyword Serializable on the object to be serialized, and third, the speed is not ideal.

Private static TOut ObjectMemoryConvert (TIn tIn) {using (MemoryStream ms = new MemoryStream ()) {BinaryFormatter formatter = new BinaryFormatter (); formatter.Serialize (ms, tIn); ms.Position = 0; return (TOut) formatter.Deserialize (ms);}}

The 1 million execution time is 8545.9835ms, which is supposed to be faster than Json serialization, but it is actually much slower.

5 、 AutoMapper

Familiar with AutoMapper, the performance did not let us down.

/ / create MapperConfigvar config = new MapperConfiguration outside the loop (cfg = > cfg.CreateMap ()); var mapper = config.CreateMapper (); / / call UserInfo newInfo = mapper.Map (info) inside the loop

The 1 million execution time is 267.5073ms, ranking third.

6. Expression tree

Here comes the big story, where the code comes from the blog at the beginning of the article, and the performance is amazing. The principle is the combination of reflection and expression tree, first using reflection to obtain fields and then caching them, and then using expression trees to assign values.

Public static class TransExp {private static readonly Func cache = GetFunc (); private static Func GetFunc () {ParameterExpression parameterExpression = Expression.Parameter (typeof (TIn), "p"); List memberBindingList = new List (); foreach (var item in typeof (TOut). GetProperties ()) {if (! item.CanWrite) continue; MemberExpression property = Expression.Property (parameterExpression, typeof (TIn) .GetProperty (item.Name)) MemberBinding memberBinding = Expression.Bind (item, property); memberBindingList.Add (memberBinding);} MemberInitExpression memberInitExpression = Expression.MemberInit (Expression.New (typeof (TOut)), memberBindingList.ToArray ()); Expression lambda = Expression.Lambda (memberInitExpression, new ParameterExpression [] {parameterExpression}); return lambda.Compile ();} public static TOut Trans (TIn tIn) {return cache (tIn);}}

Call

UserInfo newInfo = TransExp.Trans (info)

The 1 million execution time is 77.3653ms, ranking second. It's only a little slower than handwriting.

Simply sorted out into a bar chart, you can clearly compare the speed gap between these deep copy methods. To sum up, the general simple object deep copy, direct handwriting is recommended, complex object deep copy, it is recommended to use expression tree. Of course, if constructor initialization is also involved in creating an object, that is a different situation, which is not discussed here.

The complete code for this test is attached.

Using AutoMapper;using System;using System.Collections.Generic;using System.Diagnostics;using System.IO;using System.Linq.Expressions;using System.Runtime.Serialization;using System.Runtime.Serialization.Formatters.Binary;using System.Text.Json;using System.Threading.Tasks Namespace TestObjectDeepCopy {class Program {static void Main (string [] args) {UserInfo info = new UserInfo () {Name = "Zhang San", Age = 18, UserId = Guid.NewGuid () .ToString ("N"), Address = "Galactic Earth China", UpdateTime = 1615888888 CreateTime = 1615895454,} Var config = new MapperConfiguration (cfg = > cfg.CreateMap ()); var mapper = config.CreateMapper (); int count = 1000000; Stopwatch sw = new Stopwatch (); sw.Start (); for (int I =-0; I < count 39.4073ms +) {/ / handwritten 39.4073ms / / UserInfo newInfo = new UserInfo () / {/ / Name = info.Name, / / Age = info.Age, / / UserId = info.UserId, / / Address = info.Address / / UpdateTime = info.UpdateTime, / / CreateTime = info.CreateTime, / /} / / reflection 1618.4662ms / / UserInfo newInfo = TransReflection (info); / / Json string serialization 2222.2078ms / / UserInfo newInfo = JsonSerializer.Deserialize (JsonSerializer.Serialize (info)); / / object binary serialization 8545.9835ms / / UserInfo newInfo = ObjectMemoryConvert (info) / / expression tree 77.3653ms / / UserInfo newInfo = TransExp.Trans (info); / / AutoMapper 267.5073ms / / UserInfo newInfo = mapper.Map (info);} Console.WriteLine ("Total cost {0} ms.", sw.Elapsed.TotalMilliseconds); sw.Stop (); Console.ReadKey () } private static TOut TransReflection (TIn tIn) {TOut tOut = Activator.CreateInstance (); var tInType = tIn.GetType (); foreach (var itemOut in tOut.GetType (). GetProperties ()) {var itemIn = tInType.GetProperty (itemOut.Name); If (itemIn! = null) {itemOut.SetValue (tOut, itemIn.GetValue (tIn));}} return tOut } private static TOut ObjectMemoryConvert (TIn tIn) {using (MemoryStream ms = new MemoryStream ()) {BinaryFormatter formatter = new BinaryFormatter (); formatter.Serialize (ms, tIn); ms.Position = 0; return (TOut) formatter.Deserialize (ms) } public static class TransExp {private static readonly Func cache = GetFunc (); private static Func GetFunc () {ParameterExpression parameterExpression = Expression.Parameter (typeof (TIn), "p"); List memberBindingList = new List () Foreach (var item in typeof (TOut). GetProperties ()) {if (! item.CanWrite) continue; MemberExpression property = Expression.Property (parameterExpression, typeof (TIn) .GetProperty (item.Name)); MemberBinding memberBinding = Expression.Bind (item, property); memberBindingList.Add (memberBinding) } MemberInitExpression memberInitExpression = Expression.MemberInit (Expression.New (typeof (TOut)), memberBindingList.ToArray ()); Expression lambda = Expression.Lambda (memberInitExpression, new ParameterExpression [] {parameterExpression}); return lambda.Compile ();} public static TOut Trans (TIn tIn) {return cache (tIn) }} [Serializable] class UserInfo {public string Name {get; set;} public string UserId {get; set;} public int Age {get; set;} public string Address {get; set;} public long UpdateTime {get; set;} public long CreateTime {get; set The above is all the contents of the article "what is the method of deep copy of C#". Thank you for reading! I believe you will gain a lot after reading this article. The editor will update different knowledge for you every day. If you want to learn more knowledge, please pay attention to the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report