Saturday, February 18, 2012
Shallow Vs. Deep Copy
Although the concept is relatively simple, I have seen many developers struggle with the concept of shallow vs. deep copy.
First, both shallow and deep copy involves copying an object to another object. The difference lies in what is copied when the object contains a variable of reference type such as an instance of another object or an array / arraylist.
Shallow Copy
When you copy an object into another object, all the non-static members are copied from the original object to its copy. All the variables of value type are copied, but if the object contains variables of reference type, then only the reference is copied but the actual referred object is not copied. So, both the actual object and its copy refer the same instance of the object that is being referenced.
For example, consider the following class, which references another object
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace ShallowDeep
{
[Serializable]
public class Employee
{
private string _name;
private int _age;
private Address _empAddress; // reference to another class, hence a reference type.
public String Name
{
get { return _name; }
set { _name = value; }
}
public int Age
{
get { return _age; }
set { _age = value; }
}
public Address EmpAddress
{
get { return _empAddress; }
set { _empAddress = value; }
}
//method to create a shallow copy
public Employee CopyShallow(Employee EmpCopy)
{
//use MemberWiseClone to create a shallow copy
return (Employee)EmpCopy.MemberwiseClone();
}
//Method to clear a deep copy
public Employee CopyDeep(Employee EmpDeepCopy)
{
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, EmpDeepCopy);
ms.Seek(0, SeekOrigin.Begin);
Employee result = (Employee)bf.Deserialize(ms);
ms.Close();
return result;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ShallowDeep
{
public class Address
{
private String _mailingAddress;
//constructor
public Address(string MailingAddress)
{
_mailingAddress = MailingAddress;
}
public String EmpAddress
{
get{return _mailingAddress ;}
set{ _mailingAddress =value;}
}
}
} using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ShallowDeep
{
class Program
{
static void Main(string[] args)
{
//Shallow Copy
//create an instance of Employee Class
Employee oEmployee = new Employee();
oEmployee.Name="Test User";
oEmployee.Age = 30;
Address oAddress = new Address("123 Ross Street, Atlanta, GA, 12345");
oEmployee.EmpAddress=oAddress;
//Now perform a shallow copy
Employee oEmployee2 = oEmployee.CopyShallow(oEmployee);
//Now lets do the following
oEmployee2.Age = 25;
oAddress.EmpAddress = "303 Peachtree Road, Atlanta, GA, 30032";
//Check the value of oEmployee2.EmpAddress.
int empOriginalAge = oEmployee.Age;
int empCopyAge = oEmployee2.Age;
Address EmpOriginalAddr = oEmployee.EmpAddress;
Address EmpCopyAddr = oEmployee2.EmpAddress;
}
}
}
Notice the value of empOriginalAge=30 but the value of empCopyAge=25, but the value of EmpOriginalAddr and EmpCopyAddre is same i.e. "303 Peachtree Road, Atlanta, GA, 30032"
Deep Copy
To be able to deep copy an object, it must be serializable. Difference between a shallow and deep copy is that in addition to a bit by bit copy of a value object, deep copy also copies the reference object, instead of just copying only the reference to the object.
Let's use the same example as above, but instead use DeepCopy method.
Add the follow snippet to the method above.
//Deep Copy
//create an instance of Employee Class
Employee oEmployeeDeep = new Employee();
oEmployeeDeep.Name="Test User";
oEmployeeDeep.Age = 30;
Address oAddress2 = new Address("123 Ross Street, Atlanta, GA, 12345");
oEmployeeDeep.EmpAddress=oAddress2;
//Now perform a deep copy
Employee oEmployeeDeep2 = oEmployee.CopyDeep(oEmployeeDeep);
oEmployeeDeep2.Age = 25;
oAddress2.EmpAddress = "303 Peachtree Road, Atlanta, GA, 30032";
//Check the value of oEmployee2.EmpAddress.
Address EmpAddress = oEmployeeDeep2.EmpAddress;
The value of the EmpAddress will still be "123 Ross Street, Atlanta, GA, 12345".
Hope this helps clarify the difference between a shallow and deep copy. Remember, shallow sopy is done via MemberWiseClone(), while a deep copy is performed by serializing the object, hence the class must be serializable.
Just remember, the key difference is that in shallow copy only a reference to any reference type variable is copied while in deep copy, the referenced object itself is copied.
Thank you and as always, your comments are appreciated.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment