浅复制(Shallow Copy)与深复制(Deep Copy)

复制:对象的复制是生成一个与指定对象完全一样的新对象,实现的方式根据定义可以知道,新建一个类型相同的对象,然后复制原对象的每一个成员和字段。

浅复制:

 class Program
 {
 static void Main(string[] args)
 {
 ClassA A = new ClassA();
 CloneObj clone = new CloneObj();
 ClassA newA= clone.CloneA(A);
 }
 }

 public class ClassA
 {
 public Int32 AValue = 100;
 }

 public class ClassB
 {
 public Int32 BValue = 200;
 }

 public class CloneObj
 {
 public ClassA CloneA(ClassA obj)
 {
 ClassA newAobj = new ClassA();
 newAobj.AValue = obj.AValue;
 return newAobj;
 }
 }

上面的CloneObj的CloneA方法就是一个浅复制ClassA对象,修改代码:

 class Program
 {
 static void Main(string[] args)
 {
 ClassA A = new ClassA();
 CloneObj clone = new CloneObj();
 ClassA newA= clone.CloneA(A);
 }
 }

 public class ClassA
 {
 public Int32 AValue = 100;
 public ClassB objB;
 public ClassA()
 {
 objB = new ClassB();
 }
 }

 public class ClassB
 {
 public Int32 BValue = 200;
 }

 public class CloneObj
 {
 public ClassA CloneA(ClassA obj)
 {
 ClassA newAobj = new ClassA();
 newAobj.AValue = obj.AValue;
 newAobj.objB = obj.objB;
 return newAobj;
 }
 }

这里ClassA里面包含了引用类型的ClassB对象,这里复制的ClassA对象,如下图:

上面这种方式就是“浅复制(Shallow Copy)”,这里可以在调试时测试下,看看A里面objB的地址和通过复制方法出来的newA的objB的地址:

地址完全一样

浅复制是.NET默认的对象复制方式,Object类提供的Memberwise方法浅复制一个对象。实现深复制,也就是上面的图中,不是共用一个ClassB对象,而是完全创建一个新的ClassB对象。这需要实现ICloneable接口.如下:

namespace ConsoleApplication2
{
 class Program
 {
 static void Main(string[] args)
 {
 ClassA A = new ClassA();
 CloneObj clone=new CloneObj();
 ClassA newA = clone.CloneA(A);

 }
 }

 public class ClassA:ICloneable
 {
 public Int32 AValue = 100;
 public ClassB objB;
 public ClassA()
 {
 objB = new ClassB();
 }

 object ICloneable.Clone()
 {
 ClassA objA = new ClassA();
 objA.AValue = this.AValue;
 objA.objB = (this.objB as ICloneable).Clone() as ClassB;
 return objA;
 }
 }

 public class ClassB:ICloneable
 {
 public Int32 BValue = 200;

 object ICloneable.Clone()
 {
 ClassB objB = new ClassB();
 objB.BValue = this.BValue;
 return objB;
 }
 }

 public class CloneObj
 {
 public ClassA CloneA(ClassA obj)
 {
 //ClassA newAobj = new ClassA();
 //newAobj.AValue = obj.AValue;
 //newAobj.objB = obj.objB;
 ClassA newAobj = (obj as ICloneable).Clone() as ClassA;
 return newAobj;
 }
 }

}

这里完成了深复制

对象序列化

对象复制比较简单的方式是序列化,将类标记为[Serializable]。对象序列化主要解决的是对象状态的保存问题,这里所说的“对象状态”是指某一时刻对象拥有的字段值的集合。

对象的序列化:将一个内存的对象保存到流中,并在需要时从流中读取数据重建对象的过程称为“对象序列化”和“反序列化”

流:代表一连串有顺序的二进制数据。

利用序列化进行对象的复制——深复制

[Serializable]
 class MyClass
 {
 public int Index = 1;
 }

 class Program
 {
 static void Main(string[] args)
 {
 MyClass obj = new MyClass();
 //创建一个内存流对象
 using (MemoryStream ms = new MemoryStream())
 {
 IFormatter formator = new BinaryFormatter();
 formator.Serialize(ms, obj); //将对象序列化到内存流中 

 //克隆100个对象
 for (int i = 0; i < 100; i++)
 {
 ms.Seek(0, SeekOrigin.Begin);//回到流的开头
 obj = (formator.Deserialize(ms) as MyClass); //反序列化对象
 obj.Index += i; //设置对象字段
 Console.WriteLine("对象{0}已创建。", obj.Index);
 }
 }
 Console.ReadKey();
 }
 }

原理是将对象序列化到流中,然后从流中创建对象(批量),从而实现了深复制。

读书笔记《.NET4.0面向对象编程漫谈》作者:金旭亮老师

作者:张雪飞
出处:https://zhangxuefei.site/p/72
版权说明:欢迎转载,但必须注明出处,并在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

发表评论

电子邮件地址不会被公开。 必填项已用*标注