天天看点

C#系列——记一次业务需求:对象的深拷贝

 这篇随笔着实在意料之外,主要是源于上周开发BS的一个业务,需要用到对象的深拷贝。说的直白一点,就是将对象内存分配区和引用完全拷贝一份新的。这种需求以前就遇到过,怎么解决的已经记不清了。这次趁着这个机会将对象的深拷贝这个知识点记录下。

  先来说说业务场景,直接上代码:

C#系列——记一次业务需求:对象的深拷贝
C#系列——记一次业务需求:对象的深拷贝

需求就是lstAttr变量保存的是一个List<DragElementProp>类型的集合,需要遍历lstModel,需要将每一个的oModel的Name属性的值赋给lstAttr实例的Value属性。然后保存多个lstAttr的集合,形如List<List<DragElementProp>>。通过上面的代码在foreach (var oModel in lstModel)里面每次new一个新的var lstResTmp = new List<DragElementProp>();来保存赋值后lstAttr,明眼人一看就知道这种方式肯定不行,因为C#里面class是引用类型,每次改变的都是唯一的一个lstAttr实例,通过上面代码的方式得到的lstRes肯定会是几个相同的lstAttr,即最后一次赋值的lstAttr。

  怎么办?各种百度、各种博客园。查了多篇博文,发现答案千篇一律,深拷贝对象的三种解决方案:

实现ICloneable接口,自定义拷贝功能

序列化/反序列化类实现

通过反射实现

我们逐一看看这几种方式

(1)实现ICloneable接口的方式,贴上园子里面的代码

C#系列——记一次业务需求:对象的深拷贝
C#系列——记一次业务需求:对象的深拷贝

很显然,这种方式不可取。如果一个类里面有多个其他类成员,那不是每个都要去定义这样一个clone方法。太low。

(2)序列化反序列化方式。贴上园子里面的代码

C#系列——记一次业务需求:对象的深拷贝
C#系列——记一次业务需求:对象的深拷贝

这种方式比上面方式好一点,但是需要对象是可序列化的,即要加上[Serializable]特性标签,博主试过如果一个普通的类调用这个方法会报异常。

博主用Newtonsoft.Json重新写了个:

C#系列——记一次业务需求:对象的深拷贝
C#系列——记一次业务需求:对象的深拷贝

这种方式对对象没什么太特殊的要求。

(3)反射的方式,博主自己简单写了一个:

C#系列——记一次业务需求:对象的深拷贝
C#系列——记一次业务需求:对象的深拷贝

这种方式也比较简单,但考虑到反射得性能问题,而且如果是clone集合,需要遍历去反射这样效率就更低。

  综上所述:要深拷贝一个对象,其实上述无论哪种方式都是新产生一个对象,然后给新的对象依次赋值来实现。方案一一般不可取,方案二在集合的序列化方便可能效率稍微高点,方案三如果只是简单的拷贝一个对象我觉得也是不错的选择。反正博主更加偏好方案二,用起来简单。

  

  反正找了好久说的都这三种方式,这次先记录下,如果没有更好的方式就用这些方案先解决吧,当然,如果以后知道了更好的方式也可以拿出来和大家分享。也不知道.Net是否预留了某些特殊的通道来处理这种深拷贝。希望知道的大侠多多指教~~

本文转自懒得安分博客园博客,原文链接:http://www.cnblogs.com/landeanfen/p/4678534.html,如需转载请自行联系原作者