最高效率的对象深拷贝通用方法

问题描述

曾有人发帖要高效的对象拷贝通用方法,当时只给了一个简单类型的拷贝,现在挤出点时间完成了这个功能,内部的引用类型依次深度拷贝。完整代码见博客:这里发帖收集建议意见,简单的测试了下,已经非常完美的运行了,目前能支持任何带无参数的构造函数的类的深拷贝,一元数组的深拷贝,数组和类的循环嵌套深拷贝(即父子关系的类,或双向链表)。感兴趣的朋友,可以研究下Emit部分,这是C#的精华,也是能够提高效率的必备利器,嫌.NET慢的人不要光抱怨,那是因为你们不懂优化代码,会了Emit就可以最高限度的优化代码。///<summary>///创建对象深度复制的副本///</summary>publicstaticTToObjectCopy<T>(thisTsource)whereT:class///<summary>///将source对象的所有属性复制到target对象中,深度复制///</summary>publicstaticvoidObjectCopyTo<T>(thisTsource,Ttarget)whereT:class

这2个方法原型是给外部调用的,使用起来很方便,也足够了。下面说下一个很常见的使用场合,那就是实体类的复制并修改,当我们要编辑集合中的某个实体对象的内容时,又怕改错了,想提供回滚功能,就可以用它将其复制一个副本出来。虽然已经改过不少次了,但难免有BUG,欢迎提出宝贵意见。代码中的注释不多,没那么多时间完善,想学习的人可以对照MSDN慢慢看,这东西要消化很费脑细胞,慢慢琢磨吧。

解决方案

解决方案二:
先推荐,坐沙发。
解决方案三:
占位学习关注.net的性能优化。
解决方案四:
不过我还是觉得,所谓通用的深拷贝方法,应该是类库自己管理自己产生的对象时候用的。比如orm框架、rpc框架等等。而不应该去掺和用户编写的对象,因为如何正确拷贝对象,是业务逻辑考虑的事情,而不是底层层面的事情。谁写的对象,谁规定怎么拷贝。
解决方案五:
占楼学习
解决方案六:
这代码写得挺神。
解决方案七:
好东西啊,支持一下。
解决方案八:
我也有改进一个,是根据对象类型生成一个新的对象使用:Typetype=typeof(ClassName);ClassNameclassObject=(ClassName)CreateInstance.CreateInstanceByExpression(type);ClassNameclassObject=(ClassName)Activator.CreateInstance(type);///<summary>///通过表达式目录树构建对象实例(使用缓存)///.net3.5以上版本支持///</summary>publicstaticclassCreateInstance{privatestaticHashtableparamCache=Hashtable.Synchronized(newHashtable());//缓存///<summary>///根据对象类型创建对象实例///</summary>///<paramname="key">对象类型</param>///<returns></returns>publicstaticobjectCreateInstanceByExpression(Typekey){Func<object>value=(Func<object>)paramCache[key];if(value==null){value=CreateInstanceByType(key);paramCache[key]=value;}returnvalue();}privatestaticFunc<object>CreateInstanceByType(Typetype){returnExpression.Lambda<Func<object>>(Expression.New(type),null).Compile();}}

解决方案九:
FastSerialization代码太长。。
解决方案十:

解决方案十一:

解决方案十二:
刚发现了自己的代码中的一个严重BUG,不支持String类型的拷贝,因为String是特殊的引用类型,又是最常用的引用类型,处理方式几乎和值类型差不多,被我给忽略了。正在修正中。。。3楼说的在理,不过我这个是给懒人用的方法,毕竟定义类的时候去写自身的拷贝方法,一来类显得有点臃肿,二来不是自动生成的类会增加工作量,只要我这个方法用起来没任何问题,效率又高,为啥不用呢?选择C#就是为了提高开发效率,自己为每个类写拷贝方法,编程效率就降低了。
解决方案十三:
引用11楼qldsrx的回复:

刚发现了自己的代码中的一个严重BUG,不支持String类型的拷贝,因为String是特殊的引用类型,又是最常用的引用类型,处理方式几乎和值类型差不多,被我给忽略了。正在修正中。。。3楼说的在理,不过我这个是给懒人用的方法,毕竟定义类的时候去写自身的拷贝方法,一来类显得有点臃肿,二来不是自动生成的类会增加工作量,只要我这个方法用起来没任何问题,效率又高,为……

我的建议是,将这个做成一个框架。允许用户用Attribute说明如何深拷贝。然后给出不同的策略。这是实用化必须的。
解决方案十四:
改好了,博客中的代码重新编辑过了,之前复制过代码的重新复制下,也可以单独修改以下内容(这也是我代码放博客的一个原因,随时可以修改,传附件或放论坛,都没法修改)。if(!field.FieldType.IsValueType)改为了if(!field.FieldType.IsValueType&&field.FieldType!=typeof(String))因为String是不可修改的,对其不需要深拷贝,直接传其引用地址即可。
解决方案十五:
占座学习,,,以前都没有关注
其他方案:
引用12楼caozhy的回复:

我的建议是,将这个做成一个框架。允许用户用Attribute说明如何深拷贝。然后给出不同的策略。这是实用化必须的。

没问题,在这个基础上稍作修改就可以实现你要的功能,具体判断在foreach循环的时候,先获取Attribute。另外我为了提高效率,只针对了field进行拷贝,property无视,因此Attribute如果是定义在了property上面的,需要使用另一个方案——property的深度拷贝,其原理基本相同。作为抛砖引玉,如果可以看懂我写的那方法,增加自己需要的Attribute是完全没问题的,至少我目前不需要任何的限定。
其他方案:
先支持一下。
其他方案:
引用15楼qldsrx的回复:

另外我为了提高效率,只针对了field进行拷贝,property无视,因此Attribute如果是……

确实没有必要拷贝property,只需要拷贝完整的field就可以达到对象的完整拷贝,正如我们序列化对象时只需要序列化field一样。如果我们把property看成是一种method的特殊封装,更容易理解这一点。另外,其实如版主所说,通用的深拷贝其实还是有其适用场合,我觉得类似序列化,ORM等场景下使用是最合适的。
其他方案:
该回复于2013-06-23 12:30:16被版主删除
其他方案:
不错学习了,,,,,,
其他方案:
好东西啊,支持一下!!!
其他方案:
学习;顶一个;
其他方案:
学习一下,感谢楼主!
其他方案:
好东西啊,支持一下。
其他方案:
看了下,IL不是那么难理解啊。找个时间好好学习下。最后推荐大家把代码都发布到NuGet上
其他方案:
学习一下!~
其他方案:
好东西啊,支持一下。
其他方案:

其他方案:
好东西,!!!!
其他方案:
好东西啊,支持一下。
其他方案:
好东西啊,支持一下。
其他方案:
收藏,虽然不搞C
其他方案:
#好,支持一下
其他方案:
谢谢楼主分享
其他方案:
很好很好很好
其他方案:

其他方案:
楼主无私,顶起你
其他方案:
这代码写得挺神。
其他方案:
学习了,支持一下
其他方案:
okthonak
其他方案:
好东西,顺便接分
其他方案:
好东西大家看看吧
其他方案:
QQQQQQQQQQQQQQQQQQQ`
其他方案:
学习沙发,
其他方案:
饿。这种汇编的变种兄弟真心不好学呀
其他方案:

其他方案:
///<summary>///深度COPY///</summary>///<typeparamname="T"></typeparam>///<paramname="obj"></param>///<returns></returns>publicstaticTDeepClone<T>(Tobj){TobjResult;using(MemoryStreamms=newMemoryStream()){BinaryFormatterbf=newBinaryFormatter();bf.Serialize(ms,obj);ms.Position=0;objResult=(T)bf.Deserialize(ms);}returnobjResult;}

其他方案:

其他方案:
顶一个
其他方案:
赞一下。。。
其他方案:
感兴趣的朋友,可以研究下Emit部分,这是C#的精华,也是能够提高效率的必备利器,嫌.NET慢的人不要光抱怨,那是因为你们不懂优化代码,会了Emit就可以最高限度的优化代码

时间: 2024-08-31 23:48:16

最高效率的对象深拷贝通用方法的相关文章

java中List对象排序通用方法_java

本文实例讲述了java中List对象排序通用方法.分享给大家供大家参考.具体分析如下: 在数据库中查出来的列表list中,往往需要对不同的字段重新排序,一般的做法都是使用排序的字段,重新到数据库中查询.如果不到数据库查询,直接在第一次查出来的list中排序,无疑会提高系统的性能. 只要把第一次查出来的结果存放在session中,就可以对list重新排序了.一般对list排序可以使用Collections.sort(list),但如果list中包含是一个对象的话,这种方法还是行不通的.那要怎么排序

寻求赋值类对象的通用方法!!大家来顶顶啊...

问题描述 我把数据库里所有的表生成了对应的类文件,现在我要把数据表用一个list<user>形式代替,请问我有没有通用的方法对这些列表类赋值我写了点代码,但不行??///<summary>///从表中读记录并赋给一个类对象列表///</summary>publicstaticIList<T>GetObject<T>(DataTabledatatable)whereT:class,new(){Tt=null;IList<T>list=n

《Effective Java》—— 对于所有对象都通用的方法

本节主要涉及Object中通用的一些方法,比如equals,hashCode,toString,clone,finalize等等 覆盖equals时请遵守通用约定 equals方法实现的等价关系: 自反性:对于所有的非null,a=a 对称性:a=b,则b=a 传递性:a=b,b=c,则a=c 一致性:对于没有被修改的ab,如果a=b,则一直a=b 非空性:对于任何非Null,a!=null 高质量equals方法的诀窍: 使用==操作符检查--"参数是否为这个对象的引用" 使用ins

在JS中使用RecordSet对象的GetRows方法

js|对象 写ASP程序时,一般情况总是使用的VBScript,不过也不只是这一种选择,也可以用JScript.但在用JScript作为ASP的语言时,比用VBScript有一些小小的不方便,比如RecordSet的GetRows方法. 在ASP中操作数据库,一般都要用到RecordSet对象,如果注重程序效率的话,可能就会用到RecordSet对象的GetRows方法,把记录集对象转换成数组,而操作数组在速度上将比用RecordSet对象的MoveNext方法快很多,而且可以在取出数组后尽早释

ASP在JScript中使用RecordSet对象的GetRows方法

js|jscript|对象 写ASP程序时,一般情况总是使用的VBScript,不过也不只是这一种选择,也可以用JScript.但在用JScript作为ASP的语言时,比用VBScript有一些小小的不方便,比如RecordSet的GetRows方法. 在ASP中操作数据库,一般都要用到RecordSet对象,如果注重程序效率的话,可能就会用到RecordSet对象的GetRows方法,把记录集对象转换成数组,而操作数组在速度上将比用RecordSet对象的MoveNext方法快很多,而且可以在

使用泛型以及通用方法将XML与OBJECT进行相互转换

过年的这段时间一直没有闲着,总体来说可以分为以下2个部分的学习. 1:ORMCodeHelper的参考 与学习. 2:MVC3的学习. 对于ORMCodeHelper(Keny的),完全的采用插件式开发,即插即用 ,个人感觉还是比较爽的,架构不错.它包括了SQL SERVER 2000,SQL SERVER 2005以及ORACLE的相关C#代码 的生成.比哥一年前写的那个牛多了,哈哈,哥去年乱写了个网页版的 (http://www.cnblogs.com/jasenkin/archive/20

游戏中对象选取的方法

对于PC游戏,在鼠标大行其道的今天,如何由鼠标的位置判定其下的对象是什么,是几乎所有游戏都必须面对的问题. 以下提供几种方法,仅供参考. 1,包围框法.一般的,对游戏中的每个对象创建一个伴随的包围框,通过遍历所有可见对象,判定鼠标坐标点是否落在某个包围框的内部来获取其选取的对象. 这种方法的优点是简单,算法容易理解,当使用矩形包围框,而对象数量又比较有限的时候,效率也是很好的.缺点是选取不够精确,无法对对象的细节做选取. 在2D游戏中,包围框一般是矩形,或者是若干个矩形的组合,而3D游戏使用包围

通过Java泛型实现数组排序和搜索的通用方法

下面讨论的是数组的排序和搜索功能,而一个通用方法则是实现Comparable接口的方法,这个方法需要通过java泛型来实现.下面便逐步讲解为何,以及如何通过Java泛型实现此类的通用方法. 如何在java类中一些通用方法,特别是一些静态的工具方法? 比如,数组Arrays的sort.search等? 1. 整数数组的顺序收缩 public static int seqSearch(int[] arr, int first, int last, int target) { for (int i =

如何将XML与OBJECT进行相互转换(泛型以及通用方法)

对于ORMCodeHelper(Keny的),完全的采用插件式开发,即插即用,个人感觉还是比较爽的,架构不错.它包括了SQL SERVER 2000,SQL SERVER 2005以及ORACLE的相关C#代码的生成.比哥一年前写的那个牛多了,哈哈,哥去年乱写了个网页版的(http://www.cnblogs.com/jasenkin/archive/2010/02/11/1667511.html),现在看一年前的代码,哥感叹,这个谁写的代码,TMD实在写的太烂了!!!当然,ORMCodeHel