復制:對象的復制是生成一個與指定對象完全一樣的新對象,實現的方式根據定義可以知道,新建一個類型相同的對象,然后復制原對象的每一個成員和字段。
淺復制:
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面向對象編程漫談》作者:金旭亮老師