創建當前 Object 的淺表副本。
protected Object MemberwiseClone()
MemberwiseClone 方法創建一個淺表副本,方法是創建一個新對象,然後將當前對象的非靜態字段復制到該新對象。 如果字段是值類型的,則對該字段執行逐位復制。 如果字段是引用類型,則復制引用但不復制引用的對象;因此,原始對象及其復本引用同一對象。
例如,考慮對象X引用對象 A 和 B , 對象 B 依次引用對象 C。 X 的淺表副本創建一個新對象 X2,該對象也引用對象 A 和 B。 相比而言,X 的深層副本創建一個新對象 X2,該對象引用新對象 A2 和 B2(分別為 A 和 B 的副本)。 B2 又引用新對象 C2,C2 是 C 的副本。 該示例闡釋了淺層和深層復制操作之間的區別。
有很多方法可以實現深層復制操作,前提是淺表復制操作由 MemberwiseClone 方法執行但不符合您的需求。
這些要求包括:
下面的示例演示 MemberwiseClone 方法。 它定義了 ShallowCopy 方法,該方法通過調用 MemberwiseClone 方法來在 Person 對象上執行淺表復制操作。 它還定義了在 Person 對象上執行深層復制操作的DeepCopy 方法。
using System; public class IdInfo { public int IdNumber; public IdInfo(int IdNumber) { this.IdNumber = IdNumber; } } public class Person { public int Age; public string Name; public IdInfo IdInfo; public Person ShallowCopy() { return (Person)this.MemberwiseClone(); } public Person DeepCopy() { Person other = (Person) this.MemberwiseClone(); other.IdInfo = new IdInfo(this.IdInfo.IdNumber); return other; } } public class Example { public static void Main() { // Create an instance of Person and assign values to its fields. Person p1 = new Person(); p1.Age = 42; p1.Name = "Sam"; p1.IdInfo = new IdInfo(6565); // Perform a shallow copy of p1 and assign it to p2. Person p2 = (Person) p1.ShallowCopy(); // Display values of p1, p2 Console.WriteLine("Original values of p1 and p2:"); Console.WriteLine(" p1 instance values: "); DisplayValues(p1); Console.WriteLine(" p2 instance values:"); DisplayValues(p2); // Change the value of p1 properties and display the values of p1 and p2. p1.Age = 32; p1.Name = "Frank"; p1.IdInfo.IdNumber = 7878; Console.WriteLine("\nValues of p1 and p2 after changes to p1:"); Console.WriteLine(" p1 instance values: "); DisplayValues(p1); Console.WriteLine(" p2 instance values:"); DisplayValues(p2); // Make a deep copy of p1 and assign it to p3. Person p3 = p1.DeepCopy(); // Change the members of the p1 class to new values to show the deep copy. p1.Name = "George"; p1.Age = 39; p1.IdInfo.IdNumber = 8641; Console.WriteLine("\nValues of p1 and p3 after changes to p1:"); Console.WriteLine(" p1 instance values: "); DisplayValues(p1); Console.WriteLine(" p3 instance values:"); DisplayValues(p3); } public static void DisplayValues(Person p) { Console.WriteLine(" Name: {0:s}, Age: {1:d}", p.Name, p.Age); Console.WriteLine(" Value: {0:d}", p.IdInfo.IdNumber); } } // The example displays the following output: // Original values of p1 and p2: // p1 instance values: // Name: Sam, Age: 42 // Value: 6565 // p2 instance values: // Name: Sam, Age: 42 // Value: 6565 // // Values of p1 and p2 after changes to p1: // p1 instance values: // Name: Frank, Age: 32 // Value: 7878 // p2 instance values: // Name: Sam, Age: 42 // Value: 7878 // // Values of p1 and p3 after changes to p1: // p1 instance values: // Name: George, Age: 39 // Value: 8641 // p3 instance values: // Name: Frank, Age: 32 // Value: 7878
為了實現深度復制,我們就必須遍歷有相互引用的對象構成的圖,並需要處理其中的循環引用結構。這無疑是十分復雜的。幸好借助.Net的序列化和反序列化機制,可以十分簡單的深度Clone一個對象。
原理很簡單,首先將對象序列化到內存流中,此時對象和對象引用的所用對象的狀態都被保存到內存中。.Net的序列化機制會自動處理循環引用的情況。然後將內存流中的狀態信息反序列化到一個新的對象中。
這樣一個對象的深度復制就完成了。在原型設計模式中CLONE技術非常關鍵。
using System; using System.IO; using System.Runtime.Serialization.Formatters.Binary; namespace CloneDemo { [Serializable] class DemoClass { public int i = 0; public int[] iArr = { 1, 2, 3 }; public DemoClass Clone1() //淺CLONE { return this.MemberwiseClone() as DemoClass; } public DemoClass Clone2() //深clone { MemoryStream stream = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, this); stream.Position = 0; return formatter.Deserialize(stream) as DemoClass; } } class Program { static void Main(string[] args) { DemoClass a = new DemoClass(); a.i = 10; a.iArr = new int[] { 8, 9, 10 }; DemoClass b = a.Clone1(); DemoClass c = a.Clone2(); // 更改 a 對象的iArr[0], 導致 b 對象的iArr[0] 也發生了變化 而 c不會變化 a.iArr[0] = 88; Console.WriteLine("MemberwiseClone"); Console.WriteLine(b.i); foreach (var item in b.iArr) { Console.WriteLine(item); } Console.WriteLine("Clone2"); Console.WriteLine(c.i); foreach (var item in c.iArr) { Console.WriteLine(item); } Console.ReadLine(); } } }
引用:http://www.cnblogs.com/zhangji/archive/2011/02/23/1961897.html