c#表达式树实现浅拷贝对象_c# copy objects 表达式树-程序员宅基地

技术标签: c#  表达式树  浅拷贝  反射  委托  

表达式树浅拷贝对象、反射浅拷贝对象对比手写的Copy方法100万次耗时对比(CPU是 i7 - 4710MQ)
static void Main(string[] args)
{
    
    var value = new TestClass
    {
    
        Age = 18,
        Name = "张三",
        Sex = Gender.Man
    };
    Console.WriteLine("-------手写代码------");
    for (int j = 0; j < 5; j++)
    {
    
        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < 1000000; i++)
        {
    
            var copyValue = Copy(value);//手写的Copy
        }
        sw.Stop();
        Console.WriteLine("{0}ms", sw.Elapsed.TotalMilliseconds);
    }
    Console.WriteLine("-------表达式树------");
    for (int j = 0; j < 5; j++)
    {
    
        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < 1000000; i++)
        {
    
            var copyValue = ShallowCopy<TestClass>.Copy(value);//表达式树实现的Copy【程序启动的第一次Copy需要编译会慢一点】
        }
        sw.Stop();
        Console.WriteLine("{0}ms", sw.Elapsed.TotalMilliseconds);
    }
    Console.WriteLine("-------反射生成------");
    for (int j = 0; j < 5; j++)
    {
    
        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < 1000000; i++)
        {
    
            var copyValue = ShallowCopyReflect<TestClass>.Copy(value);//反射实现Copy
        }
        sw.Stop();
        Console.WriteLine("{0}ms", sw.Elapsed.TotalMilliseconds);
    }
}
public static TestClass Copy(TestClass value)
{
    
    return new TestClass
    {
    
        Age = value.Age,
        Name = value.Name,
        Sex = value.Sex
    };
}

public class TestClass
{
    
    public int Age {
     get; set; }
    public string Name {
     get; set; }
    public Gender Sex {
     get; set; }
}

public enum Gender
{
    
    Man = 0,
    Woman = 1
}

耗时:↓

-------手写代码------
42.7358ms
36.8807ms
35.0374ms
34.8473ms
35.1947ms
-------表达式树------
132.8095ms
132.7188ms
124.1226ms
124.3291ms
124.0487ms
-------反射生成------
2501.8246ms
2357.8119ms
2353.0715ms
2351.2028ms
2341.6874ms

表达式树Copy类

/// <summary>
/// 浅拷贝类
/// </summary>
/// <typeparam name="T">拷贝的类型</typeparam>
public static class ShallowCopy<T> where T : new()
{
    
    /// <summary>
    /// 浅拷贝委托对象树
    /// </summary>
    private static readonly Func<T, T> CopyFunc;

    static ShallowCopy()
    {
    
        var value = Expression.Parameter(typeof(T));
        var copyValue = Expression.New(typeof(T));
        var bindProValues = typeof(T).GetProperties().Where(w => w.CanWrite && w.CanRead).Select(pro => Expression.Bind(pro, Expression.Property(value, pro))).ToArray();
        var initProValue = Expression.MemberInit(copyValue, bindProValues);
        var lambda = Expression.Lambda<Func<T, T>>(initProValue, new[] {
     value });
        CopyFunc = lambda.Compile();
    }

    /// <summary>
    /// 拷贝方法
    /// </summary>
    /// <param name="value">需要被拷贝的值</param>
    /// <returns>拷贝的值</returns>
    public static T Copy(T value)
    {
    
        if (value == null) return default(T);
        return CopyFunc(value);
    }
}

反射实现的Copy类

/// <summary>
/// 浅拷贝类反射实现
/// </summary>
/// <typeparam name="T">拷贝的类型</typeparam>
public static class ShallowCopyReflect<T> where T : new()
{
    
    private readonly static PropertyInfo[] Properties;
    private readonly static ConstructorInfo Constructor;
    static ShallowCopyReflect()
    {
    
        Properties = typeof(T).GetProperties().Where(w => w.CanWrite && w.CanRead).ToArray();
        Constructor = typeof(T).GetConstructor(new Type[0]);
    }
    /// <summary>
    /// 拷贝方法
    /// </summary>
    /// <param name="value">需要被拷贝的值</param>
    /// <returns>拷贝的值</returns>
    public static T Copy(T value)
    {
    
        if (value == null) return default(T);
        var copyValue = Constructor.Invoke(null);
        foreach (var property in Properties)
        {
    
            property.SetValue(copyValue, property.GetValue(value));
        }
        return (T)copyValue;
    }
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43251547/article/details/103331496

智能推荐

html语言中hr是什么意思,网页制作中的hr是什么意思-程序员宅基地

文章浏览阅读5k次,点赞3次,收藏15次。网页制作中的hr是一个标签,该标签用来在html页面中创建一条水平线,这条水平线可以在视觉上将文档分割成两个部分,使用方法如【】。HR,是网页程序的标签语言, 标签在 HTML 页面中创建一条水平线。 标签在 HTML 页面中创建一条水平线水平分隔线(horizontal rule)可以在视觉上将文档分隔成两个部分。是网页编辑里的一个标签,其表现形式为一条横线。r width="90%" size..._html hr

【MySQL优化查询】MySQL单表过亿条数据,如何优化查询速度?_如果一张表是上亿级如何优化算法-程序员宅基地

文章浏览阅读2.7k次,点赞6次,收藏14次。上面主要从:垂直和水平,两个方向介绍了我们的系统为什么要分库分表。说实话垂直方向(即业务方向)更简单。在水平方向(即数据方向)上,分库和分表的作用,其实是有区别的,不能混为一谈。分库:是为了解决数据库连接资源不足问题,和磁盘IO的性能瓶颈问题。分表:是为了解决单表数据量太大,sql语句查询数据时,即使走了索引也非常耗时问题。此外还可以解决消耗cpu资源问题。分库分表:可以解决 数据库连接资源不足、磁盘IO的性能瓶颈、检索数据耗时 和 消耗cpu资源等问题。_如果一张表是上亿级如何优化算法

recyclerview实现瀑布流item位置错乱问题_安卓开发瀑布流错乱-程序员宅基地

文章浏览阅读637次,点赞12次,收藏8次。在做项目时使用瀑布流时,我们通常会想到使用recyclerview的StaggeredGridLayoutManager来实现瀑布流,并且把item布局的高度设为wrap_content,觉得这样就可以实现瀑布流了。但是等写完代码一看发现item的位置显示错乱了,这是因为我们高度使用了wrap_content,但是如果我们使用固定高度就无法实现瀑布流了,这个时候就需要我们在adapter里动态设置高度就可以解决这个问题。你也可以根据项目实际情况设置不同item的高度。_安卓开发瀑布流错乱

1. SimMechanics/Multibody入门-程序员宅基地

文章浏览阅读9.8k次,点赞43次,收藏167次。这篇博客主要介绍利用Matlab的SimMechanics/Multibody实现简单的单摆运动仿真。_simmechanics

Android 性能优化探究,作为移动开发程序员-程序员宅基地

文章浏览阅读870次,点赞22次,收藏28次。总之啊,家里没矿的同学们,如果你们想以后的日子过得好一些,多想想你们的业余时间怎么安排吧;技术方面的提升肯定是重中之重,但是技术外的一些“软实力”也不能完全忽视,很多时候升职确实是因为你的技术足够强,但也与你的“软实力”密切相关在这我也分享一份大佬自己收录整理的Android学习PDF+架构视频+面试文档+源码笔记,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅并给下属员工学习的精品资料。

Delphi防止多实例运行的两种方法《转》-程序员宅基地

文章浏览阅读83次。在学习Delphi时,遇到需要程序单实例运行的时候,经过查阅,暂时发现以下两种比较简单的方法,可以防止程序多实例运行,各有优劣,据需选择。方法一,添加以下unit即可,优点是可激活已存在的程序窗口,即使已最小化(包括最小化到托盘),缺点是可能存在与其他程序的互斥(可自行修改STR_UNIQUE的值以尽量减少该可能性)。代码如下://工程引用此单元就能防止同时出现多个实例u..._delphi 多实例

随便推点

WPF DataGrid 单元格实现下拉框选项_wpf datagrid 双击编辑时变下拉列表-程序员宅基地

文章浏览阅读3.1k次,点赞11次,收藏2次。WPF DataGrid 单元格实现下拉框选项提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录WPF DataGrid 单元格实现下拉框选项前言一、问题二、示例1.实现效果2.描述三、解决方法四、总结前言需要实现DataGrid控件单元格下拉框选项,DataGrid数据来源是数据库中的表第一次写博客,尝试一下一、问题网上有很多关于DataGridComboBoxColumn以及DataGridTemplateColumn模板列的教程,需要在前台XAML中进行添加,这_wpf datagrid 双击编辑时变下拉列表

2023年互联网黑灰产研究年度报告-程序员宅基地

文章浏览阅读54次。下载报告去公众号:硬核刘大后台回复“黑灰产”,即可下载完整PDF文件。更多报告内容,可加微信:chanpin628领取。(ps:加过微信:chanpin628 的不要再加,分享的内容一样,有一个号就行。)申明:报告版权威胁猎人所有,此处仅限分享学习使用,如有侵权,请联系小编做删除处理。..._【威胁猎人】2023年互联网黑灰产研究年度报告.pdf

[C/C++]游戏地图制作_c++ 如何做地图-程序员宅基地

文章浏览阅读705次。利用二维数组实现游戏地图_c++ 如何做地图

Ubuntu 12.04.4 LTS 部署cap-程序员宅基地

文章浏览阅读715次。一.系统环境jim@mode:~$ cat /etc/issueUbuntu 12.04.4 LTS \n \ljim@mode:~$ uname -raLinux mode 3.11.0-15-generic#25~precise1-Ubuntu SMP Thu Jan 30 17:39:31 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux二..._after this operation, 2,048 b of additional disk space will be used.

我见过最全的剖析QEMU原理的文章[Z]_no qemu-程序员宅基地

文章浏览阅读1.2w次。转自:http://people.cs.nctu.edu.tw/~chenwj/dokuwiki/doku.php?id=qemu How To Become A Hacker 写给新手程序员的一封信目录建置 QEMUUser ModeSPARCPowerP_no qemu

Dart —— 基础数据类型 Number String Boolean List Map Set Rune Symbol_dart number-程序员宅基地

文章浏览阅读714次。内建类型文章目录Dart 语言支持以下内建类型:NumberStringBooleanListSetMapRuneSymbolDart 语言支持以下内建类型:NumberStringBooleanList (也被称为 Array)MapSetRune (用于在字符串中表示 Unicode 字符)Symbol这些类型都可以被初始化为字面量。 例如, 'this is a s..._dart number