Wednesday, February 11, 2009

Write deep Clone(). Forget about ICloneable.

I was chatting with my co-worker about implementing Clone() method for our hierarchy of classes. It's not easy to implement interfaces (think about ICloneable) for class hierarchies. Some tips might be found in Implementing Interfaces at C# Online.NET article, in Implementing Interfaces: ICloneable and IComparable article, and in Advantages of ICloneable? discussion.
As Zach said, it's easier just to implement a virtual Clone() method in a base class and to override it in derived classes as necessary.

I started to look for information about ICloneable and found the following quite unequivocal guidelines:

Caution. Avoid implementing ICloneable. As alarming as that sounds, Microsoft is actually making this recommendation. The problem stems from the fact that the contract doesn’t specify whether the copy should be deep or shallow. In fact, as noted in Krzysztof Cwalina and Brad Abrams’ Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries (Boston, MA: Addison-Wesley Professional, 2005), Cwalina searched the entire code base of the .NET Framework and couldn’t find any code that uses ICloneable. Had the Framework designers and developers been using this interface, they probably would have stumbled across the omission in the ICloneable specification and fixed it.
However, this recommendation is not to say that you shouldn’t implement a Clone method if you need one. If your class needs a clone method, you can still implement one on the public contract of the class without actually implementing ICloneable.

Accelerated C# 2008

Because the contract of ICloneable does not specify the type of clone implementation required to satisfy the contract, different classes have different implementations of the interface. Consumers cannot rely on ICloneable to let them know whether an object is deep-copied or not. Therefore, we recommend that ICloneable not be implemented.
The moral of the story is that you should never ship an interface if you don't have both implementations and consumers of the interface. In the case of ICloneable, we did not have consumers when we shipped it. I searched the Framework sources and could not find even one place where we take ICloneable as a parameter.
x DO NOT implement ICloneable.
x DO NOT use ICloneable in public APIs.
x CONSIDER defining the Clone method on types that need a cloning mechanism. Ensure that the documentation clearly states whether it is a deep- or shallow-copy.

Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries

Comments (4)

Loading... Logging you in...
  • Logged in as
Login or signup now to comment.
David Parsons's avatar

David Parsons · 779 weeks ago

I have also been discussing this subject with colleagues at work. Opinions vary, and some of my co-workers are pretty much of the same opinion as Vladimir.

I do, however, think that there is no need to specify if a Clone method performs a deep or shallow copy. If I Clone an object all I care about is that the cloned object has exactly the same status as the original object. I want to be able to use it without being concerned about trashing anything else. It is up to the implementer of the class to ensure that the Clone method supports this.
In some cases this will mean a deep copy - but not always. It may be more appropriate to deep copy some members and not others.

If a consumer of a class wants a shallow copy then there is always MemberwiseClone, which is inherited from Object.
Reply
Ahmad hasan k's avatar

Ahmad hasan k · 777 weeks ago

overload the Clone method like :
public object Clone()
{
return this.MemberwiseClone();
}

public object Clone(bool isdeep)
{
if (isdeep)
{
return CopyDeep();
}
else
{
return Clone();
}
}
Reply
Clone never used? Well, I would bet that I had seen ICloneable.Clone used inside System.Windows.Forms.DataGridViewColumn when the Column object instantiates new Cell object from its CellTemplate..
Reply
There is a need where you wan to clone an object for your custom requirement you need to "ICloneable" Interface and Implement Clone() Method, the inbuilt Clone() method does not fulfill custom requirement.
Visit this link for view C#.Net Example , VB.Net Examples with Sample downloadable application.
http://jayeshsorathia.blogspot.com/2012/10/net-ti...
Reply

Comments by