BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

.NET Framework
.NET 3.5+

Deep Cloning Using Binary Serialization

Cloning is the process of creating copies of objects or object graphs. The .NET framework provides methods for creating shallow copies, where a single object is cloned. Deep cloning can be achieved in several manners, including using serialization.

Cloning

A common development task is to create a copy of an object. The System.Object class, and therefore all reference types that inherit from it, includes the MemberwiseClone method. This creates a shallow copy of an object by duplicating all non-static fields. If those fields themselves contain instances of reference types, only the reference is copied. This means that the original field and its duplicate refer to the same object. Changes to either object will therefore be seen in its counterpart.

Deep cloning is the process of creating a duplicate of an entire object graph. Unlike with a shallow copy, a deep copy recursively copies an object's fields and those of any child objects. When complete, the copied object does not share any references with the original.

There are several ways in which a deep clone of an object graph can be created. One way is to take advantage of binary serialization. By serializing an object to a stream, then deserializing the stream, a perfect duplicate is generated. This process works with all types that support serialization.

In this article we will create a simple extension method that creates a deep clone of an object using binary serialization.

DeepClone Extension Method

Before creating the DeepClone method, we need a static class. Create a new console application and add a class named "DeepCloneExtensions". If you use the standard template for a C# class you will need to add the static keyword. The class definition should be as follows:

public static class DeepCloneExtensions
{
}

The DeepClone method will accept an object of any type and return an object of the same type. This is an ideal situation in which to use a generic method. Inside the method we need to follow several steps. First, we will create a new stream to receive the serialized data of the source object. This will be a MemoryStream to ensure the best performance possible. We can then use a BinaryFormatter to serialize the source object into the stream.

Once the data has been serialized, the position within the stream must be reset so that subsequent reads start from the first byte of data. We can then deserialize the information to a new object using the binary formatter. Finally, the object will be cast to the original type and returned. The completed extension method is as follows:

public static T DeepClone<T>(this T toClone)
{
    using (var stream = new MemoryStream())
    {
        var formatter = new BinaryFormatter();
        formatter.Serialize(stream, toClone);
        stream.Seek(0, SeekOrigin.Begin);
        return (T)formatter.Deserialize(stream);
    }
}

As the extension method's first parameter is of type T, the method can be called without providing a type parameter. The type returned will be inferred and will match that of the source object. To demonstrate, add the following code to the Main method of the console application and execute the program in debug mode. Step through code and examine the content of the cloned objects to see the results.

var myDictionary = new Dictionary<int, string>();
myDictionary.Add(1, "One");
myDictionary.Add(2, "Two");
myDictionary.Add(3, "Three");

var clone = myDictionary.DeepClone();
4 June 2010