C#深拷贝效率对比

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

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博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/256676.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【算法系列篇】递归、搜索和回溯(四)

文章目录 前言什么是决策树1. 全排列1.1 题目要求1.2 做题思路1.3 代码实现 2. 子集2.1 题目要求2.2 做题思路2.3 代码实现 3. 找出所有子集的异或总和再求和3.1 题目要求3.2 做题思路3.3 代码实现 4. 全排列II4.1 题目要求4.2 做题思路4.3 代码实现 前言 前面我们通过几个题目…

idea恢复默认出厂设置

idea恢复默认出厂设置 1、IDEA 2021 之后&#xff0c; 在顶部工具栏&#xff0c;选择 File | Manage IDE Settings | Restore Default Settings. 2、或者双击shift搜索Restore Default settings然后点击restore and restart

企业微信无法给Gmail发邮件问题

问题说明 在使用企业微信给国外客户的Gmail邮箱发信件的时候&#xff0c;邮件一直被退信&#xff0c;退信内容如下&#xff1a; 发件人&#xff08;*******.cn&#xff09;域名的DNS记录未设置或设置错误导致对方拒收此邮件。 host gmail-smtp-in.l.google.com[142.251.175.2…

左右按钮实现滚动轮播Demo(js手搓版本)

提示&#xff1a;适用于当放置按钮空间区域有限&#xff0c;通过左右箭头实现有限空间放置更多的按钮的情形&#xff0c;自适应布局的简单Demo支持二次开发和改造 文章目录 效果图Demo源码解释说明总结 效果图 在该区域存在五个按钮&#xff0c;点击左边按钮向左边滚动&#xf…

查看git的帮助信息

说明 在cmd窗口、或者git Bash shell下执行git --help或者git -h命令&#xff0c;可以查看git的帮助信息。 执行git <command> --help命令可以查看某个命令的帮助信息&#xff0c;其中<command>表示某个具体的命令。 示例1&#xff1a;在git Bash shell下运行git…

新能源线束电接头气密测试快速工装

线束气密测试是新能源车生产过程中必须要测试流程&#xff0c;包括常规的电缆测试、电接头测试、接线端子测试等。需要用到相应的快速接头来密封连接线束一端&#xff0c;进行充气或封堵&#xff0c;并连接上检漏仪等相关设备&#xff0c;检查产品密封防水合格性。 线束快速密封…

Vue3 Element Plus自定义年份区间选择组件

环境&#xff1a; "dependencies": {"rollup/plugin-alias": "^3.1.9","types/node": "^17.0.43","element-plus": "^2.2.15","three": "^0.148.0","vue": "^3.2.…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Button按钮组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Button按钮组件 一、操作环境 操作系统: Windows 10 专业版 IDE:DevEco Studio 3.1 SDK:HarmonyOS 3.1 二、Button按钮组件 Button 组件也是基础组件之一&#xff0c;和其它基础组件不…

【深度学习】Prompt

1.Prompt的通俗解释 Prompt就是“提示”的意思&#xff0c;通俗解释可以参考你画我猜游戏。如下图所示&#xff1a;提示词就作为Prompt&#xff0c;指导对方说出正确答案。而自然语言处理任务中的Prompt也有同样的效果&#xff0c;指导模型输出正确的答案。 2.Prompt的不通俗解…

【密码学】群的证明(习题)

0.前置知识 1.习题 记录一次密码学作业~群的判定 2.求解

Linux发行版比较:Ubuntu、CentOS、Red Hat与其他系统的优劣分析

导言 Linux作为开源操作系统&#xff0c;有众多不同的发行版&#xff0c;每个发行版都有其独特的特性和适用场景。本文将聚焦于比较Ubuntu、CentOS、Red Hat和其他系统&#xff0c;深入分析它们的优势、用途以及在不同领域的应用。Linux操作系统的生态系统中&#xff0c;Ubuntu…

传输层—TCP核心机制(确认应答、超时重传、三次握手四次挥手、滑动串口等……)

传输层—TCP核心机制 ​ 文章目录 传输层—TCP核心机制TCP1.1 确认应答机制 (可靠传输机制)1.2 超时重传机制 (可靠传输机制)1.3 连接管理机制 (可靠传输机制)1.3.1 三次握手&#xff08;建立连接&#xff09;1.3.2 四次握手&#xff08;断开连接&#xff09; 1.4 滑动窗口 (提…

如何使用示波器探头对被测电路进行检测

对电路信号进行检测之前首先要知道被测电路是什么电路&#xff0c;被测信号是什么信号。盲目地测试或者使用不正确的测量方法&#xff0c;有可能得到错误的波形甚至损坏仪器危及安全。 1、什么是差分信号&#xff1f;什么是单端信号&#xff1f; 差分传输是一种信号传输的技术…

Selenium自动化测试框架(超详细总结分享)

设计思路 本文整理归纳以往的工作中用到的东西&#xff0c;现汇总成基础测试框架提供分享。 框架采用python3 selenium3 PO yaml ddt unittest等技术编写成基础测试框架&#xff0c;能适应日常测试工作需要。 1、使用Page Object模式将页面定位和业务操作分开&#xff…

SecureCRT for Mac/win强大安全的终端SSH工具,SecureCRT助您网络连接无忧

在当今数字化时代&#xff0c;网络连接已成为生活和工作中不可或缺的一部分。而对于需要进行远程访问和管理的用户来说&#xff0c;一个稳定、安全的终端SSH工具是至关重要的。SecureCRT作为一款强大的终端SSH工具&#xff0c;为用户提供了安全、高效的远程连接解决方案。 首先…

如何压缩视频发邮件?帮你整理了几个必备的!

不同邮件附件上限大小有所不同&#xff0c;QQ邮箱的附件大小限制为2GB&#xff0c;这意味着用户可以发送最大为2GB的视频文件&#xff1b;Gmail邮箱的附件大小限制为25MB&#xff1b;163邮箱的附件大小限制为2GB&#xff0c;但是为了保证文件传输的成功率&#xff0c;建议最好不…

SpringBoot 多环境开发配置文件

在开发过程中&#xff0c;往往开发环境和生产环境需要不同的配置。为了兼容两种运行环境&#xff0c;提高开发效率&#xff0c;可以使用多环境开发配置文件。 配置文件结构大概是这样&#xff1a; application.yml -主启动配置文件&#xff08;用于控制使用哪种环境配…

金和OA jc6 clobfield接口存在SQL注入漏洞

文章目录 产品简介漏洞概述指纹识别漏洞利用修复建议 产品简介 金和OA协同办公管理系统j6软件是一种综合性的协同办公解决方案&#xff0c;旨在提高企业内部的协作效率和工作效率。它提供了一系列功能和工具&#xff0c;帮助组织进行任务管理、日程安排、文件共享、团队协作和…

关于腾讯位置服务路线规划-微信小程序-插件未授权使用

我们点击添加插件会发现添加错误,主要是因为他说不开放给个人用户. 这是我们可以进入微信服务市场直接搜索腾讯位置服务路线规划 | 微信服务市场 (qq.com)点击添加插件即可完成

实战|Smartbi---意外的福利

目录 漏洞描述 影响版本 fofa语法 漏洞复现 构造poc 修复建议 本文由掌控安全学院 - beize 投稿 漏洞描述 Smartbi在安装时会内置几个用户&#xff0c;在使用特定接口时&#xff0c;可绕过用户身份认证机制获取其身份凭证&#xff0c;随后可使用获取的身份凭证调用后台…