C# Best Practice: Implementing ICloneable Interface for deep copy

Many time we need to provide deep copy method to our classes. As we know in C#.net every object is derived from class Object and Object class provides some methods, in which one is

protected object MemberwiseClone();

MemberwiseClone cannot be overridden, and is only accessible through this class or a derived class. Creates a shallow copy of the current System.Object.

A shallow copy created is new object of current type and copies all non static variables in newly created object. Value type will be copied bit by bit and for reference types only references are copied not object.

In following example

class Address
{
public string flat;
public string phone;
}
class MyInfo: ICloneable
{
public static string CompanyName = "My Company";
public int age;
public string name;
public Address address;

public object Clone()
{
//This makes only shallow copy
//Values of age and name will be copied
//But of address as it is ref type only ref is copied
MyInfo infoNew = (MyInfo)this.MemberwiseClone();
return infoNew;
}
}

In I have implemented clone method by implementing Iclonable but this clone method will make only Shallow copy of MyInfo.

class Test
{
public static void Sample()
{
MyInfo info = new MyInfo();
info.name = "Anupama";
info.age = 31;
Address add = new Address();
add.flat = "28-D";
add.phone = "288888888";
info.address = add;

MyInfo infoNew = (MyInfo)info.Clone();
infoNew.address.flat = "28-D New";

MessageBox.Show(info.address.flat);

}
}

In above example info.clone() will make shallow copy of info object. Means if you change values of address in infoNew object them it will also change in info.address object(it will show 28-D New) because MemberwiseClone method copies only reference of  reference type.

For implementing clone method for deep copy you should implement as given below. Implement ICloneable in all reference type properly as given below.

Read comments in following code carefully and you can test this sample bay running it.

class Address : ICloneable
{
public string flat;
public string phone;

public object Clone()
{
return this.MemberwiseClone();
}
}
class MyInfo: ICloneable
{
public static string CompanyName = "My Company";
public int age;
public string name;
public Address address;

public object Clone()
{
//This makes only shallow copy
//Values of age and name will be copied
//But of address as it is ref type only ref is copied
MyInfo infoNew = (MyInfo)this.MemberwiseClone();
//Make deep copy by calling clone method of Address class
//This will make new object of type address 
//Copy value type fields flat and phone
Address addressNew = (Address)this.address.Clone();
//Assigne new copy object of Address to newInfo address
//New Old info and new InfoNew has seperate copies of all
//Fileds
infoNew.address = addressNew;
return infoNew;
}
}

class Test
{
public static void Sample()
{
MyInfo info = new MyInfo();
info.name = "Anupama";
info.age = 31;
Address add = new Address();
add.flat = "28-D";
add.phone = "288888888";
info.address = add;

MyInfo infoNew = (MyInfo)info.Clone();
infoNew.address.flat = "28-D New";

MessageBox.Show(info.address.flat);

}
}

Or you can write your own logic to do deep copy in clone methods for deep/shallow copy by initializing new object and assigning non static fields values manually.

But that it never a good practice.

Leave a Reply

Your email address will not be published. Required fields are marked *