C#深拷贝效率对比

发布时间:2023年12月17日

对于浅拷贝和深拷贝,前面的文章已经说明了。

C#浅拷贝和深拷贝数据-CSDN博客

? ? ? ? 本篇说一下,深拷贝的效率问题,效率一直是程序追求的,效率越高肯定越好,有时候功能是实现了,但是运行以及处理数据的效率非常低,此时就让人很头疼,当你知道了如何提高效率的时候,在你实现功能的时候,就已经考虑进去了,而不是先把功能做好,后期再优化(当然这种模式覆盖大部分人的开发习惯)。

测试1:

使用共同的数据结构和100W数量,分别对比4种深拷贝的效率问题。

1.反射

耗时:3465?

2.JSON字符串序列化

耗时: 7095

3.表达式树

耗时:396?

4.AutoMapper

耗时:682?

结论:
表达式树>AutoMapper>反射>JSON。如果数据结构非常复杂而且多,那么就使用表达式树。?

测试2:

使用共同的数据结构和10W数量,分别对比4种深拷贝的效率问题。

1.反射

耗时:498

2.JSON字符串序列化

耗时: 1072

3.表达式树

耗时:243

4.AutoMapper

耗时:268

结论:

表达式树>AutoMapper>反射>JSON

代码:


using AutoMapper;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static WpfApp4.MainWindow;
using Expression = System.Linq.Expressions.Expression;

namespace WpfApp4
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Stopwatch sw = new Stopwatch();
            sw.Start();
            var config = new MapperConfiguration(cfg => cfg.CreateMap<TestData1, TestData1>());//映射配置
            for (int i = 0; i < 10_0000; i++)
            {
                TestData3 testData3 = new TestData3();
                testData3.ID = 3 + i;
                testData3.D1 = "3.1" + i.ToString();
                testData3.D2 = "3.2" + i.ToString();

                TestData2 testData2 = new TestData2();
                testData2.ID = 2 + i;
                testData2.D1 = "2.1" + i.ToString();
                testData2.D2 = "2.2" + i.ToString();
                testData2.testData3 = testData3;

                TestData1 testData1 = new TestData1();
                testData1.ID = 1 + i;
                testData1.D1 = "1.1" + i.ToString();
                testData1.D2 = "1.2" + i.ToString();
                testData1.testData2 = testData2;
                //反射效率
                //var test2 = DeepCopyWithReflection(testData1);

                //JSON字符串序列化效率
                //var test3 = JsonConvert.DeserializeObject<TestData1>(JsonConvert.SerializeObject(testData1));

                //表达式树效率
                //var test4 = TransExp<TestData1, TestData1>.Trans(testData1);

                //AutoMapper效率
                var test5 = config.CreateMapper().Map<TestData1>(testData1);

            }
            double count = sw.Elapsed.TotalMilliseconds;
            sw.Stop();
            int a = 0;
        }



        /// <summary>
        /// 利用反射实现深拷贝
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T DeepCopyWithReflection<T>(T obj)
        {
            Type type = obj.GetType();

            // 如果是字符串或值类型则直接返回
            if (obj is string || type.IsValueType) return obj;
            // 如果是数组
            if (type.IsArray)
            {
                Type elementType = Type.GetType(type.FullName.Replace("[]", string.Empty));
                var array = obj as Array;
                Array copied = Array.CreateInstance(elementType, array.Length);
                for (int i = 0; i < array.Length; i++)
                {
                    copied.SetValue(DeepCopyWithReflection(array.GetValue(i)), i);
                }
                return (T)Convert.ChangeType(copied, obj.GetType());
            }

            object retval = Activator.CreateInstance(obj.GetType());

            PropertyInfo[] properties = obj.GetType().GetProperties(
                BindingFlags.Public | BindingFlags.NonPublic
                | BindingFlags.Instance | BindingFlags.Static);
            foreach (var property in properties)
            {
                var propertyValue = property.GetValue(obj, null);
                if (propertyValue == null)
                    continue;
                property.SetValue(retval, DeepCopyWithReflection(propertyValue), null);
            }

            return (T)retval;
        }
        /// <summary>
        /// 表达式树
        /// </summary>
        /// <typeparam name="TIn"></typeparam>
        /// <typeparam name="TOut"></typeparam>
        public static class TransExp<TIn, TOut>
        {
            private static readonly Func<TIn, TOut> cache = GetFunc();
            private static Func<TIn, TOut> GetFunc()
            {
                ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
                List<MemberBinding> memberBindingList = new List<MemberBinding>();

                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<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[] { parameterExpression });

                return lambda.Compile();
            }

            public static TOut Trans(TIn tIn)
            {
                return cache(tIn);
            }

        }

    }
}

总结:总的来说,数据量在100W的时候,差距还是很明显的,建议使用表达式树,在10W数量的时候,表达式树和AutoMapper差距已经不是很大了,数据量再小的话,预计差别就更少了,具体使用,还是看程序的数据在什么量级。

源码:

https://download.csdn.net/download/u012563853/88637623

本文来源:

C#深拷贝效率对比-CSDN博客

文章来源:https://blog.csdn.net/u012563853/article/details/135046541
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。