Wednesday 19 November 2008

Cloning objects in C# / Performing a Deep Copy

I’ve come from a C++ background as many C# programmers seem to have.  Once of the things that will eventually bite you in the foot once you move to .NET is that not only is everything passed by reference, but the language does not support cloning or deep copying of an object. 

When you copy an object there are two ways to do it.  The first is a shallow copy where your copy result references the same in memory object as your original as follows.

image

Obviously here any changes to the original will be made to the copy as well.  This is not really a copy of the object but a copy of the reference, and it is the most common way to copy an object in C# and .NET.

The other way is a deep copy.  A deep copy makes a duplicate of the original object for the new reference as follows.

image

Changes to your original object will no longer effect the copied object.  But guess what, there is no way to do this cleanly in C#.

Before anyone jumps up and down and says that there are ways to do this, well yes there are some methods:

1. Binary Serialization

You can serialize the object and restore it into the copy.  This will work but it will require that the class that you’re copying is serlializable.

2. XML Serialization

You can serialize the object to XML and restore it into the copy.  This will not require that you have the class as serializable, but it will only copy the public members and properties.

3. Reflection

I’ve used reflection a fair bit and it’s very nice, but if you wish to make a generic Clone method it will not let you set private members and nested objects will be harder to do in this fashion.

4. Custom Clone Method

If you implement the IClonable (I wouldn’t suggest it as it appears that it will be deprecated at some point in the future) or your own cloneable base class or interface all objects that implement it could be manually copied using reflection with access to private members.  But any classes that do not inherit from your custom clonable class will not be able to be cloned (the entity framework for example).

What it all boils down to is that if you have private members that are not serializable then you will not be able to clone or deep copy the object, and if this is true then it would make all sense to never do it.  In my opinion this is not necessarily a bad thing, but a design choice of the Microsoft developers.  As long as you’re aware of it then developing around it should be simple enough, if you hack a solution to the problem into place then you are destined to come across issues in the future.

No comments: