Clone serializable objects in C#


[clone]

If a class is serializable, then you can create a deep clone of an object from that class by serializing it and the deserializing it. This example uses the following code to define a generic extension method that clones objects from any serializable class.

// Return a deep clone of an object of type T.
public static T DeepClone<T>(this T obj)
{
    using (MemoryStream memory_stream = new MemoryStream())
    {
        // Serialize the object into the memory stream.
        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Serialize(memory_stream, obj);

        // Rewind the stream and use it to create a new object.
        memory_stream.Position = 0;
        return (T)formatter.Deserialize(memory_stream);
    }
}

The code creates a BinaryFormatter and uses it to serialize the object into a memory stream. It then uses the formatter to deserialize the stream into a new object.

Using this extension method is simple. The following code shows how the example program uses it to make a deep clone of the object named person1.

person3 = person1.DeepClone();

For this to work, the class must be marked as serializable. The clone also only includes members of the class that are serializable. For example, if some of the class’s properties are marked with the XmlIgnore attribute, then they won’t be serialized or deserialized so the clone won’t get the original object’s values for those properties.

This example serializes a Person object. The following code shows the Person class’s declaration.

[Serializable()]
class Person : ICloneable
{
    ...
}

The Person class has an Address property that is of the StreetAddress class. That class is also marked serializable so the DeepClone method can copy its value into the new Person object.


Download Example   Follow me on Twitter   RSS feed   Donate




This entry was posted in algorithms, OOP, syntax and tagged , , , , , , , , , , , , , . Bookmark the permalink.

5 Responses to Clone serializable objects in C#

  1. Mike says:

    This was interesting, but what I’d like to know now is what’s involved in creating serializable classes?

    Also what about attached properties?

    And does deserialization use the class’s property setters so any side effects of the setter would be invoked or not? This is probably related to my 1st question about how to make a class serializable.

    A future article on these questions would be awesome. Thanks.

  2. Rod Stephens says:

    The basics are fairly easy. Just add the Serializable attribute (in the System.ComponentModel namespace) to the class.

    There are other attribute that can modify how properties are serialized. For example, you can make a property be serialized as an XML attribute instead of as a separate element, or you can make the serialization ignore a property. See these posts for some more details:

    I’m not sure how attached properties work with serialization. I haven’t worked with serialization in WPF.

    Finally, yes the serializers and deserializers use the class’s property methods rather than setting backing variables directly so any side effects would take place. In particular, deserializers create an object before setting any of its properties so they require that there be a constructor that takes no parameters (so they can initially make the object). This is occasionally a bit annoying but I don’t know of any good way around it.

    I hope that helps. Let me know if you have other questions.

  3. Mike says:

    Thanks Rod,
    Yes that helps. I haven’t followed your links yet, but I may later.

    So marking an object Serializable seems like it would be useful only for simpler objects, and implementing ICloneable is probably the way to go for more complex objects where there are private fields which need copying to the clone, and events that maybe should not be fired etc.

  4. Rod Stephens says:

    ICloneable would be more useful if Microsoft had included a parameter to tell you whether you should make a shallow or deep clone. As it is, your results may vary and you need to be careful not to create mixed results such as a deep clone that includes fields that refer to objects that were cloned shallowly. (If that makes sense.)

    • The serialization trick is most useful when:
    • You are using someone else’s class and they didn’t provide a deep clone method.
    • Your class includes references to other classes that are serializable but that don’t provide deep clone methods.
    • Your class is very complex and the code changes regularly so keeping a Clone method up to date would be hard.
    • Several people are working on your class’s code so it would be hard to keep a Clone method up to date as they make changes.
    • As you suggest, there are side effects in the class’s empty constructor and property procedures that you want to avoid. (Although it may be worth rewriting the code to remove those side effects in any case.)

    In general I would:

    • Make ShallowClone and DeepClone methods, or a single Clone method that takes a parameter to indicate whether it should be a shallow or deep clone.
    • If you need to implement ICloneable, do so by calling either ShallowClone or DeepClone.
  5. Pingback: Clone lists and arrays of objects in C# - C# HelperC# Helper

Leave a Reply

Your email address will not be published. Required fields are marked *