Shallow Clone and Deep Clone
Shallow Clone and Deep Clone
If you want to add a clone method to a custom class, the ICloneable interface must be implemented. Here’s a sample:
class Class1 : ICloneable
{
public int x = 10;
public virtual Object Clone()
{
return MemberwiseClone();
}
}
We use a “MemberwiseClone” method in Class1. the method is from Object class, it is protected, so it can only be invoked in a derived class of Object. The method will perform a shallow clone operation.
If we have a class – Class3, the class inherits from Class1.Here’s sample:
{
public int y = 10;
public virtual Object Clone()
{
return MemberwiseClone();
}
}
class Class3 : Class1 // shallow clone
{
public int z = 10;
public Class2 c2 = new Class2();
public override Object Clone()
{
return base.Clone();
}
}
Now we invoke the Clone method of Class3 to copy the Class3 object.
Class3 c3 = new Class3();
Class3 c3_clone = (Class3)c3.Clone();
Console.WriteLine("c3.z = " + c3.z.ToString());
Console.WriteLine("c3_clone.z = " + c3_clone.z.ToString());
Console.WriteLine("c3.c2.y = " + c3.c2.y.ToString());
Console.WriteLine("c3_clone.c2.y = " + c3_clone.c2.y.ToString());
c3.z = 20;
c3.c2.y = 40; // The both c2.y(c3 and c3_clone) are altered.
Console.WriteLine("c3.z = " + c3.z.ToString());
Console.WriteLine("c3_clone.z = " + c3_clone.z.ToString());
Console.WriteLine("c3.c2.y = " + c3.c2.y.ToString());
Console.WriteLine("c3_clone.c2.y = " + c3_clone.c2.y.ToString());
You can find a problem from above code. When 40 is assigned to the “c3.c2.y”, the value of the “c3_clone.c2.y” also is changed. This is because that the reference of c3.c2 is as same as the one of c3_clone.Namely their refered objects are same.
The running result is:
c3.z = 10
c3_clone.z = 10
c3.c2.y = 10
c3_clone.c2.y = 10
c3.z = 20
c3_clone.z = 10
c3.c2.y = 40
c3_clone.c2.y = 40
Then we should how to solve the problem. Ok, that is deep clone. Please look at the code of Class4.
class Class4 : Class1 // deep clone
{
public int z = 10;
public Class2 c2 = new Class2();
public override Object Clone()
{
Object obj = base.Clone();
((Class4)obj).c2 = (Class2)c2.Clone();
return obj;
}
}
Class4 c4 = new Class4();
Class4 c4_clone = (Class4)c4.Clone();
Console.WriteLine("c4.z = " + c4.z.ToString());
Console.WriteLine("c4_clone.z = " + c4_clone.z.ToString());
Console.WriteLine("c4.c2.y = " + c4.c2.y.ToString());
Console.WriteLine("c4_clone.c2.y = " + c4_clone.c2.y.ToString());
c4.z = 20;
c4.c2.y = 40;
Console.WriteLine("c4.z = " + c4.z.ToString());
Console.WriteLine("c4_clone.z = " + c4_clone.z.ToString());
Console.WriteLine("c4.c2.y = " + c4.c2.y.ToString());
Console.WriteLine("c4_clone.c2.y = " + c4_clone.c2.y.ToString());
Seeing from above code, the c4_clone.c2.y still is 10.
The running result is
c4.z = 10
c4_clone.z = 10
c4.c2.y = 10
c4_clone.c2.y = 10
c4.z = 20
c4_clone.z = 10
c4.c2.y = 40
c4_clone.c2.y = 10
The whole code is on https://files.cnblogs.com/bughole/clone.rar
The sample must be run in visual studio 2005.
浙公网安备 33010602011771号