代码改变世界

MemberwiseClone C#克隆

2012-07-19 15:44  假面Wilson  阅读(355)  评论(0编辑  收藏  举报
MemberwiseClone方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用单不复制引用的对象;因此院士对象及其副本引用同一对象。
例如,考虑引用对象A和B的被称为X的对象。对象B依次引用对象C。X的浅表副本创建一个新对象X2,该对象也引用对象A和B。相比而言,X的深层副本创建一个新对象X2,该对象引用新对象A2和B2(人别为A和B的副本)。B2有引用新对象C2,C2是C的副本。该实例阐释了千层和深层复制操作之间的区别。
有很多方法可以实现深层复制操作,前提是浅表赋值操作有MemberwiseClone方法执行但不符合您的要求。这些要求包括:
  • 调用要复制的对象的构造函数以创建含有从第一个对象中提出的属性值的第二个对象。这假定对象的值完全由类构造函数定义。
  • 调用MemberwiseClone方法创建的对象的浅表副本,然后将指定新的对象,其值均相同,院士对象的任何属性或字段的值是引用类型。该实例中的DeepCopy方法阐释了这种方法。
  • 序列化要深层复制的对象,然后将序列化的数据还原到另一个对象变量。
  • 使用带递归的反射执行的深层复制操作。
下面的实力掩饰MemberwiseClone方法。它定义了ShallowCopy方法,该方法通过调用MemberwiseClone方法来在Person对象上执行浅表复制操作。他还定义了在Person对象上执行深层复制操作的DeepCopy方法。
View Code 
 1 using System;
 2 public class IdInfo
 3 {
 4     public int IdNumber;
 5     public IdInfo(int IdNumber)
 6     {
 7 this.IdNumber=IdNumber;
 8     }
 9 }
10 
11 public class Person
12 {
13     public int Age;
14     public string Name;
15     public IdInfo IdInfo;
16     public Person ShallowCopy()
17     {
18 return (Person)this.MemberwiseClone();
19     }
20     public Person DeepCopy()
21     {
22 Person other=(Person)this.MemberwiseClone();
23 other.IdInfo=new IdInfo(this.IdInfo.IdNumber);
24 return other;
25     }
26 }
27 
28 public class Example
29 {
30     public static void Main(string[] args)
31     {
32 Person p1=new Person();
33 p1.Age=42;
34 p1.Name="Sam";
35 p1.IdInfo=new InInfo(6565);
36 
37 Person p2=(Person)p1.ShallowCopy();
38 
39 Console.WriteLine("Original values of p1 and p2:");
40 Console.writeLine("   p1.instance values: ");
41 Console.writeLine("   p2.instance values: ");
42 DisplayValues(p2);
43 
44 p1.Age=32;
45 p1.Name="Frank";
46 p1.IdInfo.IdNumber=7878;
47 Console.WriteLine("\nValues of p1 and p2 after changes to p1:");
48 Console.WriteLine("   p1 instance values: ");
49 DisplayValues(p1);
50 Console.WriteLine("   p2 instance values: ");
51 DisplayValues(p2);
52 
53 Person p3=p1.DeepCopy();
54 p1.Name="George";
55 p1.Age=39;
56 p1.IdInfo.IdNumber=8641;
57 Console.WriteLine("\nValues of p1 and p3 after changes to p1:");
58 Console.WriteLine("   p1 instance values: ");
59 DisplayValues(p1);
60 Console.WriteLine("   p3 instance values: ");
61 DisplayValues(p3);
62     }
63 
64     public static void DisplayValues(Person p)
65     {
66 Console.WriteLine("   Name: {0:s}, Age: {1:d}",p.Name,p.Age);
67 Console.WriteLine("   Value: {0:d}",p.InInfo.IdNumer);
68     }
69 }
70 // The example displays the following output:  
71 // Original values of p1 and p2:  
72 // p1 instance values:  
73 // Name: Sam, Age: 42  
74 // Value: 6565  
75 // p2 instance values:  
76 // Name: Sam, Age: 42  
77 // Value: 6565  
78 //  
79 // Values of p1 and p2 after changes to p1:  
80 // p1 instance values:  
81 // Name: Frank, Age: 32  
82 // Value: 7878  
83 // p2 instance values:  
84 // Name: Sam, Age: 42  
85 // Value: 7878  
86 //  
87 // Values of p1 and p3 after changes to p1:  
88 // p1 instance values:  
89 // Name: George, Age: 39  
90 // Value: 8641  
91 // p3 instance values:  
92 // Name: Frank, Age: 32  
93 //