Cloning an object in C# is a surprisingly less straightforward topic than one might think it to be. Cloning is especially needed in crud applications where you want to have the ability to reset data for a form without contacting the database again and without clearing the form. Before I talk of how I used it I’ll just share how I managed the cloning.
Memberwise vs Deep Cloning
The first discovery I made was that there are two forms of cloning available. Shallow and deep. (Are those the real terms? I think I should rebrand this blog as a noob’s take on programming). Shallow cloning aka Memberwise clone is generally enough for any situation. The problem with directly saying
Object a = b (where ‘b’ is of the same Object type as ‘a’) is that as far as basic OOP concepts go you are simply copying the reference. Therefore there’s no point in this clone since any changes simply get reflected in ‘a’. To do a b.clone() call you can implement the icloneable interface but that’s actually an unnecessary step and I’m still trying to find out why bother with it
TODO: Research why one should use the icloneable interface
Back to the matter of memberwise/shallow vs deep cloning. Memberwise cloning basically takes all the individual members of your object and and copies it into a new object. The only real problem here is that you have to make an expensive cast upon returning it since it ends up being returned as an object. Well, relatively expensive anyway but since you realistically won’t be casting a billion objects in a single operation this probably isn’t too bad. The real problem in this method is when an object contains instances of other objects as part of it’s parameter group.
What happens inside when cloning memberwise.
MyClass toBeClonedTo = (MyClass)objectToClone.MemberWiseClone(); results in:
MyClass tobeClonedTo = new MyClass();
tobeClonedTo.paramA = objectToClone.paramA;
tobeClonedTo.paramB = objectToClone.paramB;
But what happens when there is an object inside the object?
toBeClonedTo.MyClass2instance = objectToClone.MyClass2.instance
This ends up just copying the pointer to that object. Which means that if any changes are made to that particular instance it affects the cloned object as well which means whatever you did can be thought of as pretty useless.
Deep cloning on the other hand is something that has to be implemented by the programmer and is about cloning every piece of information. Cloning. Not ‘Cloning’. Essentially all you have to do is return a new object of MyClass type with the variables instantiated the way you want them to. If you are in control of all the classes, you might as well call the memberwiseclone method in the other objects as well (eventually everything is made up of basic types) and put those into the constructor.
public MyClass DeepClone()
return new MyClass(this.paramA, this.paramB, (MyClass2)this.MyClass2instance.ShallowClone()
Where the MyClass2 will have a method called ShallowClone() that calls the this.MemeberWiseClone() method. Do note that the above example I made of memberwise cloning was incorrect code and was just to illustrate the concept.
And there you have it. Deep Cloning for objects that have instances of other objects in them as parameters. Shallow Cloning or Memberwise Cloning for Objects containing only primitive types.