Use MemberwiseClone the ICloneable interface in C#


[MemberwiseClone]

The example Clone objects in C# explains how to give a class a Clone method that makes copies of its objects. This example makes two changes: it implements the ICloneable interface and it uses MemberwiseClone to simplify the cloning code.

Cloning is a fairly common and useful task, so Microsoft defined the ICloneable interface to make it easier to use classes that provide a Clone method. The ICloneable interface defines a single Clone method that takes no parameters and returns a clone of the object. Microsoft’s definition of the interface does not specify whether this should be a shallow or deep clone–you should return whichever is appropriate for the class.

To maximize flexibility, this example’s Person class keeps the same Clone method from the previous example that takes a parameter indicating whether the clone should be shallow or deep. It then adds the following overloaded version of the Clone method that takes no parameters to satisfy the ICloneable interface.

// Make a deep clone of the person.
public object Clone()
{
    return Clone(CloneType.Deep);
}

This method simply calls the version of Clone defined earlier to return a deep clone.

To simplify the previously defined Clone method, this version of the Person class uses the Object class’s MemberwiseClone method. That method uses reflection to examine an object’s properties and then copies their values into a new object. It doesn’t do anything smart with the properties, it simply copies them, so the result is a shallow clone.

For example, the Person class has an Address property of type StreetAddress. The MemberwiseClone method copies the value of that property instead of creating a new StreetAddress object so the result is a shallow clone.

The following code shows the new Clone method.

// Make a clone of the person.
public Person Clone(CloneType clone_type)
{
    // Make a shallow clone.
    Person new_person = (Person)MemberwiseClone();

    // If this should be a deep clone, make a new Address object.
    if (clone_type == CloneType.Deep)
    {
        new_person.Address = (StreetAddress)Address.Clone();
    }

    // Return the new Person.
    return new_person;
}

The code starts by using MemberwiseClone to make a shallow clone. Then if it should be making a deep clone, the method creates a new StreetAddress object.

This example also makes its StreetAddress class implement ICloneable. The following code shows that class’s Clone method.

// This class has no reference type properties
// so a shallow clone is the same as a deep clone.
public object Clone()
{
    return MemberwiseClone();
}

You could also define an overloaded Clone method that takes a parameter to indicate which kind of clone to return, but the StreetAddress class has no reference properties so its shallow and deep clones are the same.

The MemberwiseClone method is protected in the Object class, so it can only be used inside a class that inherits from Object. All classes inherit from Object so that’s not a big restriction, but it means code outside of the class cannot invoke it. For example, the Person class cannot invoke the MemberwiseClone method for a StreetAddress object. That means if you want to be able to clone objects from a class, you must define a Clone method inside that class. And in that case you may as well implement ICloneable, too.

In the next post I’ll describe a trick that lets you make a deep clone of some classes without defining a Clone method for them.


Download Example   Follow me on Twitter   RSS feed   Donate




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

Leave a Reply

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