ICloneable

Recently I wanted to create a class that had the ability to clone itself. Here is a simple example class:

internal class CloneableObject
{
     private string message;

     internal CloneableObject(string message)
     {
         this.message = message;
     } 
}

upon implementing the ICloneable interface I noticed the interface specified the return type of object.

#region ICloneable Members

public object Clone()
{
     return new CloneableObject("A am a IClonable object");
}

#endregion

My initial opinion was that this wasn't that helpful. You are only ever going to want a CloneableObject returned from CloneableObject.Clone() and I would prefer to avoid casting for runtime type safety and performance.

I can appreciate why IClonable is like this, its not like you can implement your interface in a generic way, e.g.

public interface ICloneable
{
    <T> Clone();
}

So, I implemented both ways. One way for those consumers that know it is a ClonableObject and the other way for those who just care that its IClonable.

internal class CloneableObject : ICloneable
{
    private string message;

    internal string Message { get { return message; } }

    internal CloneableObject(string message)
    {
        this.message = message;
    }

    internal CloneableObject Clone()
    {
        return new CloneableObject("I am a CloneableObject");
    }

    #region ICloneable Members

    object ICloneable.Clone()
    {
        return new CloneableObject("I am ICloneable");
    }

    #endregion
}

At this point I should point out that I know it should be return new CloneableObject(this.message) as it should be creating a copy of the original not just making up the members, but for this example, it suits.

My next question was, which Clone() gets called when?

The obvious answer is object ICloneable.Clone() when the consumer treats it as a ICloneable object and CloneableObject Clone() when treated as a Cloneable object.

static void Main(string[] args)
        {
            CloneableObject first = new CloneableObject("original");
            ICloneable second = new CloneableObject("original");

            Console.WriteLine(first.Clone());
            Console.WriteLine(second.Clone());
            Console.ReadLine();
        }

image

Best of both worlds in my opinion. I guess the question to ask is why are you implementing ICloneable? Do you consumer classes care?

Comments

# re: ICloneable
Gravatar You're quite correct in spotting that a lot of the basic interfaces such as ICloneable return a System.Object, and it's quite clear that they don't have much choice in the matter. I think your solution is just fine - if the caller knows what they are dealing with then they can call the strongly typed version (and save having an ugly cast in their code), if not they can call the ICloneable version. They are unlikely to try to cast the result of ICloneable, since they don't know what type to cast it to (if they did, they could have used the strongly typed method).

There would be a temptation to define an interface like this:

interface ICloneable<T>
{
T Clone();
}

and then your CloneableObject can look like this:

class CloneableObject : ICloneable<CloneableObject>
{
public CloneableObject Clone()
{
// suitable code here
}
}

however, much as this looks nice, you've pretty much lost the benefits of having the interface in the first place. ICloneable is useful because you can pass it around the system without needing to know what is being cloned. ICloneable<T> is less useful, since it in not polymorphic in the same way. Specifically, ICloneable<Circle> cannot be passed into a method that expects an ICloneable<Shape>, even if Circle derives from Shape. This means that you pretty much have to know what T is the whole time, at which point it has kind of lost its usefulness.

Two comments on your code. Firstly, ICloneable.Clone can just call the CloneableObject.Clone method directly, which saves having duplicated code (although for your example, it would have made the console readout less useful!). So you can have this:

class CloneableObject : ICloneable
{
public CloneableObject Clone()
{
// suitable code here
}

object ICloneable.Clone()
{
return Clone();
}
}

Secondly, I would not expect your clone method to call "new CloneableObject(this.Message)" - what happens when you add a new field that needs copying? It would be better to define another constructor (privately, if possible) that take an instance of a CloneableObject as its parameter, i.e.:

private CloneableObject(CloneableObject other)
{
// suitable code here
}

now when you need to clone, you just:

return new CloneableObject(this);

and it's only the copy constructor that you need to change should you change your fields.
Left by Steve Strong on 10/2/2008 1:55 PM
# re: ICloneable
Gravatar Thanks Steve.

Totally agree. If the consumer knows the type then they would use ICloneableObject and if they don't then they would use ICloneable. As for the code, it was purely for demonstration to get the correct output in the console. The real world class I was implementing this in uses MemberwiseClone();
Left by Neil Jenman on 10/2/2008 4:39 PM

Leave Your Comment

Title*
Name*
Email (never displayed)
 (will show your gravatar)
Url
Comment*

Please add 3 and 5 and type the answer here:

Preview Your Comment.