Thursday, July 8, 2010

To clone or not to clone

Have you ever needed to copy an object’s values to another object of the same type? If you have and have done this manually by copying each value separately this blog entry is for you. In this post I will guide you to make the object cloning process as easy as possible.

Let's say you have the following classes

public class Person
{
public Person()
{ }

private string _FirstName = "";
private string _LastName = "";
private Car _Car = new Car();

public string FirstName
{
get { return _FirstName; }
set { _FirstName = value; }
}

public string LastName
{
get { return _LastName; }
set { _LastName = value; }
}
public Car PersonCar
{
get{return _Car;}
set{_Car=value;}
}
}

public class Car
{
public Car()
{ }

private string _Make = "";

public string Make
{
get { return _Make; }
set { _Make = value;
}
}
I will now create two instances of this class. One where I create the Person object from scratch and another where I assign the new person to be the same as Person One.

Person personOne = new Person();
personOne.FirstName="Peter";
personOne.LastName = "Cane";

Person personTwo = new Person();
personTwo = personOne ;

If this code is executed, the values of the two person objects will be the same. But when you change the FirstName of person two, the the FirstName of person one will also change. When you use the equals (=) sign to assign an object to another object, you only copy the reference to the actual values. If you change any propery of any of the person object, the value will change for person one and person two. Thus a change made in one instance will also affect the other instance directly because they are the same instance with different names.

To copy the actual values of the object and create a new object, you need to implement the ICloneble interface. To implement this interface add the following to your class declaration.

class Program :ICloneable

When you implement this interface, the following method is added to your class. You need to implement the method so that is does the cloning for you.

public object Clone()
{
throw new Exception("The method or operation is not implemented.");
}

Types of cloning

There are two types of cloning. Shallow copy and a deep copy of the object. Shallow copy will clone the objects value types,but will only copy the references of any reference types in the object. For example, let’s say you clone the Person object created above using shallow copy. The person will be cloned, but the car object will not be cloned. In other words the new Person will still use the other guy’s car. To clone the object so that both have their own car, you have to use deep copy. A car will be cloned for the new guy as well.

• Shallow Copy : use the MemberwiseClone function. This will copy the value types, but only copy the references to the reference types

public object Clone()
{
this.MemberwiseClone();
}
• Deep Copy : To implement a deep copy, you will need to serialize the object and then deserialize the object as follows.

public object Clone()
{
MemoryStream mm = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(mm, this);
mm.Seek(0, SeekOrigin.Begin);
object o;
o = bf.Deserialize(mm);
return o;
}

In this instance I would say cloning is the optimum solution, as for cloning sheep….I don't agree.

Dewald Fortier.

No comments:

Post a Comment