This is basically the concept of creating the copy of an object. Sometimes you required to create a clone of an object then you can either achieve by using ICloneable interface or you can directly use MemberwiseClone() with ‘this’ keyword inside the method declaration in original class.
Shallow copy and Deep copy both are basically do similar things; copying ‘Value type’ member bit by bit. But when you have reference type in your original class then the difference between both comes into the light.
Herer is what happens with reference type when using MemberwiseClone() method-
Shallow copy copies don’t copy the reference to new memory but it create a new reference pointing to the same member object of original class. Its don’t create new memory to copy the object. See below diagram. Here 'm' is original object and 'm2' is its shallow copy.
Reference type created by Shallow copy is still pointing to parent(Original) member object.
Deep copy copies not only copies the value types but also provide new memory object with new reference for reference type member in the new copy class. See below diagram. Here 'm' is the same parent object and 'm3' is its deep copy.
Below is the code example how we can achieve Shallow Copy and Deep Copy of an object in C# using MemberwiseClone() method -
The output of the above code would be like -
m2 is taking Shallow copy of m
m.value = Amit and My job is - Developer in department IT
m2.value = Sunil and My job is - Developer in department IT
m2.value = Sunil and My job is - Developer in department Architecture
m.value = Amit and My job is - Developer in department Architecture
-----------------
m3 is taking Deep copy of m
m.value = Amit and My job is - Developer in department IT
m3.value = Sunil and My job is - Developer in department Architecture
m2.value = Sunil and My job is - Developer in department Architecture
m.value = Amit and My job is - Developer in department IT
In the first output when changed the value of sub object in original it changed in the Shallow copied object as well. So be careful while you choose to copy the Object with MemberwiseClone();
Shallow copy and Deep copy both are basically do similar things; copying ‘Value type’ member bit by bit. But when you have reference type in your original class then the difference between both comes into the light.
Herer is what happens with reference type when using MemberwiseClone() method-
Shallow copy copies don’t copy the reference to new memory but it create a new reference pointing to the same member object of original class. Its don’t create new memory to copy the object. See below diagram. Here 'm' is original object and 'm2' is its shallow copy.
Reference type created by Shallow copy is still pointing to parent(Original) member object.
Deep copy copies not only copies the value types but also provide new memory object with new reference for reference type member in the new copy class. See below diagram. Here 'm' is the same parent object and 'm3' is its deep copy.
Below is the code example how we can achieve Shallow Copy and Deep Copy of an object in C# using MemberwiseClone() method -
public class Job
{
public string job = "";
public string Department = "";
public override string ToString()
{
return "My job is - " + this.job + " in department " + this.Department;
}
}
public class MyClass
{
public string name = "";
public Job myjob;
public MyClass ShallowCopy()
{
return (MyClass)this.MemberwiseClone();
}
public MyClass DeepCopy()
{
MyClass temp = (MyClass)this.MemberwiseClone();
//Creating a new memory for the object and setting same values from the original
temp.myjob = new Job { Department = this.myjob.Department, job = this.myjob.job };
return temp;
}
}
class Program
{
static void Main(string[] args)
{
MyClass m = new MyClass();
m.name = "Amit";
m.myjob = new Job { Department = "IT", job = "Developer" };
MyClass m2 = m.ShallowCopy();
m2.name = "Sunil";
Console.WriteLine("m2 is taking Shallow copy of m");
Console.WriteLine("m.value = " + m.name +" and " +m.myjob);
Console.WriteLine("m2.value = " + m2.name + " and " + m2.myjob);
m.myjob.Department = "Architecture";
Console.WriteLine("m2.value = " + m2.name + " and " + m2.myjob);
Console.WriteLine("m.value = " + m.name + " and " + m.myjob);
Console.WriteLine("\n-----------------");
Console.WriteLine("m3 is taking Deep copy of m");
MyClass m3 = m.DeepCopy(); // m3 will persist the departement as Architecture
m3.name = "Sunil";
m.myjob.Department = "IT"; // Here we're changing the Original m's member object to IT
Console.WriteLine("m.value = " + m.name + " and " + m.myjob);
Console.WriteLine("m3.value = " + m3.name + " and " + m3.myjob);
Console.WriteLine("m2.value = " + m3.name + " and " + m3.myjob);
Console.WriteLine("m.value = " + m.name + " and " + m.myjob);
}
}
{
public string job = "";
public string Department = "";
public override string ToString()
{
return "My job is - " + this.job + " in department " + this.Department;
}
}
public class MyClass
{
public string name = "";
public Job myjob;
public MyClass ShallowCopy()
{
return (MyClass)this.MemberwiseClone();
}
public MyClass DeepCopy()
{
MyClass temp = (MyClass)this.MemberwiseClone();
//Creating a new memory for the object and setting same values from the original
temp.myjob = new Job { Department = this.myjob.Department, job = this.myjob.job };
return temp;
}
}
class Program
{
static void Main(string[] args)
{
MyClass m = new MyClass();
m.name = "Amit";
m.myjob = new Job { Department = "IT", job = "Developer" };
MyClass m2 = m.ShallowCopy();
m2.name = "Sunil";
Console.WriteLine("m2 is taking Shallow copy of m");
Console.WriteLine("m.value = " + m.name +" and " +m.myjob);
Console.WriteLine("m2.value = " + m2.name + " and " + m2.myjob);
m.myjob.Department = "Architecture";
Console.WriteLine("m2.value = " + m2.name + " and " + m2.myjob);
Console.WriteLine("m.value = " + m.name + " and " + m.myjob);
Console.WriteLine("\n-----------------");
Console.WriteLine("m3 is taking Deep copy of m");
MyClass m3 = m.DeepCopy(); // m3 will persist the departement as Architecture
m3.name = "Sunil";
m.myjob.Department = "IT"; // Here we're changing the Original m's member object to IT
Console.WriteLine("m.value = " + m.name + " and " + m.myjob);
Console.WriteLine("m3.value = " + m3.name + " and " + m3.myjob);
Console.WriteLine("m2.value = " + m3.name + " and " + m3.myjob);
Console.WriteLine("m.value = " + m.name + " and " + m.myjob);
}
}
The output of the above code would be like -
m2 is taking Shallow copy of m
m.value = Amit and My job is - Developer in department IT
m2.value = Sunil and My job is - Developer in department IT
m2.value = Sunil and My job is - Developer in department Architecture
m.value = Amit and My job is - Developer in department Architecture
-----------------
m3 is taking Deep copy of m
m.value = Amit and My job is - Developer in department IT
m3.value = Sunil and My job is - Developer in department Architecture
m2.value = Sunil and My job is - Developer in department Architecture
m.value = Amit and My job is - Developer in department IT
In the first output when changed the value of sub object in original it changed in the Shallow copied object as well. So be careful while you choose to copy the Object with MemberwiseClone();
what is the difference between MemberwiseClone and if we serialize and deserialize to make a clone?
ReplyDeleteas far as i concern, basically MemberwiseClone() is shallow copy, but if you do serialize & deserialize it will turn your class/struct into burst of bytes so it wont copy reference from original class which is equal to deep copy. CMIIW
Delete1. why did you print m2 value with m3
ReplyDelete"Console.WriteLine("m2.value = " + m3.name + " and " + m3.myjob);"
2. In the end of the line, why print m value twice, there is no change after first print of m. Might be useless print
Thank you btw
That must be a typo. But thanks for the feedback I think I should be writing a new and detailed version of this blog with all details of memory allocation and copy references. It was a blog when I started with C#. Today when I read it I get it that it is lacking explanation and better code example. Thankyou for your time for writing the feedback.
ReplyDelete