Cloning objects in .NET

In an interesting project where I'm giving a hand, we need to clone objects of a number of different types, perhaps surprisingly the CLR doesn't offer a general cloning method, of course you could use MemberwiseClone() but this is a protected method, so it can be invoked only from inside the class of the object being cloned, which makes it difficult to use it in a general method, besides, MemberWiseClone() does just a shallow copy and what we really need is a deep copy.

There is a good reason for not having such a general method: object cloning is one of those problems which have a simple solution for simple scenarios but that resist a satisfactory solution for all the scenarios, for example the objects may have references to other objects and even to themselves be it directly or after a long chain, for example a customer has invoices that have payments that refer to the customer, a general cloning algorithm for a web several times more complex than that is anything but trivial. But the need of moving objects (and their web) is inescapable in distributed environments, because you have to move the invoices and the customers from the business layer to the presentation layer, so there are indeed mechanisms, albeit with some limitations, for serializing and deserializing object graphs, with the help of these mechanisms we can try and build a general object cloner:

    1 

    2     public static T BinaryClone<T>(this T originalObject)

    3     {

    4         using (var stream = new System.IO.MemoryStream())

    5         {

    6             var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

    7             binaryFormatter.Serialize(stream, originalObject);

    8             stream.Position = 0;

    9             return (T)binaryFormatter.Deserialize(stream);

   10         }

   11     }

   12 

We just convert, using as intermediary a memory stream, our object to a bit string and then we synthesize a *new object* from that bit string. The use of BinaryClone() flows nicely:

    1 

    2     var clone = person.BinaryClone();

    3 

Easy to write, but we have to be careful of the performance and the corner cases. I run a few *very informal* performance tests with this object:

    1 

    2     var person = new Person

    3     {

    4         Id = 101,

    5         Name = "Sánchez, Sebastián",

    6         Salary = 590.20m,

    7         BirthDate = new DateTime(2000, 6, 15),

    8         Address = new Address { Number = "N24-78", Street = "Pasaje Córdova" }

    9     };

   10 

And I found that doing a hundred thousand clones takes some nine thousand milliseconds, that is each cloning takes less than one ten-thousandth of a second, which is adequate to our needs. BinaryFormatter has been with us since .NET Framework 1.0 so I'm not like saying anything even remotely new or unknown, but tomorrow (or the day after, or the day after...) I'll talk about a small refinement to BinaryClone().

3 Comments

Comments have been disabled for this content.