MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。 如果字段是值类型的,则对该字段执行逐位复制。 如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。
例如,考虑引用对象 A 和 B 的被称为 X 的对象。 对象 B 依次引用对象 C。 X 的浅表副本创建一个新对象 X2,该对象也引用对象 A 和 B。 相比而言,X 的深层副本创建一个新对象 X2,该对象引用新对象 A2 和 B2(分别为 A 和 B 的副本)。 B2 又引用新对象 C2,C2 是 C 的副本。 该示例阐释了浅层和深层复制操作之间的区别。
有很多方法可以实现深层复制操作,前提是浅表复制操作由 MemberwiseClone 方法执行但不符合您的需求。 这些要求包括:
-
调用要复制的对象的类构造函数以创建含有从第一个对象中提出的属性值的第二个对象。 这假定对象的值完全由类构造函数定义。
-
调用 MemberwiseClone 方法创建的对象的浅表副本,然后将指定新的对象,其值均相同,原始对象的任何属性或字段的值是引用类型。 该示例中的 DeepCopy 方法阐释了这种方法。
-
序列化要深层复制的对象,然后将序列化的数据还原到另一个对象变量。
-
使用带递归的反射执行的深层复制操作。
1 using System;
2
3 public class IdInfo
4 {
5 public int IdNumber;
6
7 public IdInfo(int IdNumber)
8 {
9 this.IdNumber = IdNumber;
10 }
11 }
12
13 public class Person
14 {
15 public int Age;
16 public string Name;
17 public IdInfo IdInfo;
18
19 public Person ShallowCopy()
20 {
21 return (Person)this.MemberwiseClone();
22 }
23
24 public Person DeepCopy()
25 {
26 Person other = (Person) this.MemberwiseClone();
27 other.IdInfo = new IdInfo(this.IdInfo.IdNumber);
28 return other;
29 }
30 }
31
32 public class Example
33 {
34 public static void Main()
35 {
36 // Create an instance of Person and assign values to its fields.
37 Person p1 = new Person();
38 p1.Age = 42;
39 p1.Name = "Sam";
40 p1.IdInfo = new IdInfo(6565);
41
42 // Perform a shallow copy of p1 and assign it to p2.
43 Person p2 = (Person) p1.ShallowCopy();
44
45 // Display values of p1, p2
46 Console.WriteLine("Original values of p1 and p2:");
47 Console.WriteLine(" p1 instance values: ");
48 DisplayValues(p1);
49 Console.WriteLine(" p2 instance values:");
50 DisplayValues(p2);
51
52 // Change the value of p1 properties and display the values of p1 and p2.
53 p1.Age = 32;
54 p1.Name = "Frank";
55 p1.IdInfo.IdNumber = 7878;
56 Console.WriteLine("\nValues of p1 and p2 after changes to p1:");
57 Console.WriteLine(" p1 instance values: ");
58 DisplayValues(p1);
59 Console.WriteLine(" p2 instance values:");
60 DisplayValues(p2);
61
62 // Make a deep copy of p1 and assign it to p3.
63 Person p3 = p1.DeepCopy();
64 // Change the members of the p1 class to new values to show the deep copy.
65 p1.Name = "George";
66 p1.Age = 39;
67 p1.IdInfo.IdNumber = 8641;
68 Console.WriteLine("\nValues of p1 and p3 after changes to p1:");
69 Console.WriteLine(" p1 instance values: ");
70 DisplayValues(p1);
71 Console.WriteLine(" p3 instance values:");
72 DisplayValues(p3);
73 }
74
75 public static void DisplayValues(Person p)
76 {
77 Console.WriteLine(" Name: {0:s}, Age: {1:d}", p.Name, p.Age);
78 Console.WriteLine(" Value: {0:d}", p.IdInfo.IdNumber);
79 }
80 }
81 // The example displays the following output:
82 // Original values of p1 and p2:
83 // p1 instance values:
84 // Name: Sam, Age: 42
85 // Value: 6565
86 // p2 instance values:
87 // Name: Sam, Age: 42
88 // Value: 6565
89 //
90 // Values of p1 and p2 after changes to p1:
91 // p1 instance values:
92 // Name: Frank, Age: 32
93 // Value: 7878
94 // p2 instance values:
95 // Name: Sam, Age: 42
96 // Value: 7878
97 //
98 // Values of p1 and p3 after changes to p1:
99 // p1 instance values:
100 // Name: George, Age: 39
101 // Value: 8641
102 // p3 instance values:
103 // Name: Frank, Age: 32
104 // Value: 7878