关于深拷贝和浅拷贝的文章已经颇多。http://cnn237111.blog.51cto.com/2359144/589507
简单的说,深拷贝和浅拷贝都是拷贝对象。但是当拷贝的对象中有包含引用类型对象时,深拷贝和浅拷贝的做法就又不一样了。
浅拷贝对该子对象只是拷贝了一个引用,实际上指向的还是拷贝对象的那份数据。
深拷贝则不然,是重新开辟内存空间,将子对象玩玩整整的复制一份。
下面是一个演示的例子。
在看演示之前,对几个方法做一下说明。
object.ReferenceEquals方法,比较两个实例是否是引用了同一个对象,即两个引用变量指向的是同一个内存地址。不要去对值类型调用ReferenceEquals方法,因为ReferenceEquals接收的是object类型,值类型传进去后会被装箱,每次装箱都会有一个新的地址,因此两个相等的值类型传进去,得到的结果也是false。
ObjectIDGenerator.GetId方法,该方法是获得指定对象的ID,同样的对值类型数据,不要调用此方法。
MemberwiseClone()方法,该方法创建当前 Object 的浅表副本,即返回当前对象的一个浅拷贝。下面摘自MSDN:
MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。
MemberwiseClone方法是protected的,因此只能在类内部,或者派生类中使用。要实现深拷贝的话,还需自己实现。
在下面的演示中,可以看到string变量的违法常规的特殊行为,这是由于字符串的驻留的机制,可以参考文章:http://www.cnblogs.com/artech/archive/2007/03/04/663728.html
示例代码:
- namespace ConsoleApplication1
- {
- class Program
- {
- static ObjectIDGenerator IDGenerator = new ObjectIDGenerator();
- static void Main(string[] args)
- {
- bool isFirstTime;
- testObject t1 = new testObject();
- testObject t2 = t1.ShallowCopy();
- Console.WriteLine("浅拷贝后......");
- Console.WriteLine(string.Format("t1的ObjectID={0}。t2的ObjectID={1}。ReferenceEquals(t1, t2)={2}", IDGenerator.GetId(t1, out isFirstTime), IDGenerator.GetId(t2, out isFirstTime), object.ReferenceEquals(t1, t2)));
- Console.WriteLine(string.Format("t1.i == t2.i {0}",t1.i == t2.i));
- Console.WriteLine(string.Format("t1.s的ObjectID={0}。t2.s的ObjectID={1}。ReferenceEquals(t1.s, t2.s)={2}", IDGenerator.GetId(t1.s, out isFirstTime), IDGenerator.GetId(t2.s, out isFirstTime), object.ReferenceEquals(t1.s, t2.s)));
- Console.WriteLine(object.ReferenceEquals(t1.sb, t2.sb));
- Console.WriteLine(string.Format("t1.sb的ObjectID={0}。t2.sb的ObjectID={1}。ReferenceEquals(t1.sb, t2.sb)={2}", IDGenerator.GetId(t1.sb, out isFirstTime), IDGenerator.GetId(t2.sb, out isFirstTime), object.ReferenceEquals(t1.sb, t2.sb)));
- Console.WriteLine();
- testObject t3 = t1.DeepCopy();
- Console.WriteLine("深拷贝后......");
- Console.WriteLine(string.Format("t1的ObjectID={0}。t3的ObjectID={1}。ReferenceEquals(t1, t3)={2}", IDGenerator.GetId(t1, out isFirstTime), IDGenerator.GetId(t3, out isFirstTime), object.ReferenceEquals(t1, t3)));
- Console.WriteLine(string.Format("t1.i == t3.i {0}", t1.i == t3.i));
- Console.WriteLine(string.Format("t1.s的ObjectID={0}。t3.s的ObjectID={1}。ReferenceEquals(t1.s, t3.s)={2}", IDGenerator.GetId(t1.s, out isFirstTime), IDGenerator.GetId(t3.s, out isFirstTime), object.ReferenceEquals(t1.s, t3.s)));
- Console.WriteLine(object.ReferenceEquals(t1.sb, t3.sb));
- Console.WriteLine(string.Format("t1.sb的ObjectID={0}。t3.sb的ObjectID={1}。ReferenceEquals(t1.sb, t3.sb)={2}", IDGenerator.GetId(t1.sb, out isFirstTime), IDGenerator.GetId(t3.sb, out isFirstTime), object.ReferenceEquals(t1.sb, t3.sb)));
- }
- }
- public class testObject
- {
- public int i = 0;
- public string s = "";
- public StringBuilder sb = new StringBuilder();
- public testObject ShallowCopy()
- {
- return (testObject)this.MemberwiseClone();
- }
- public testObject DeepCopy()
- {
- testObject other = (testObject)this.MemberwiseClone();
- other.s = new String(this.s.ToCharArray());
- other.sb = new StringBuilder(this.sb.ToString());
- return other;
- }
- }
- }
运行结果: