Reputation: 28652
I just wanted to know what is the use of IClonable interface in .NET?
Upvotes: 9
Views: 3974
Reputation: 31
What about defining IShallowClone and IDeepClone like this?
public interface IShallowClone<T> { T ShallowClone(); }
public interface IDeepClone<T> { T DeepClone(); }
public interface IA : IShallowClone<IA>, IDeepClone<IA> { double a { get; } IA ia { get; } }
public interface IB : IA, IShallowClone<IB>, IDeepClone<IB> { double b { get; } IB ib { get; } }
public class A : IA
{
public double a { get; private set; }
public IA ia { get; private set; }
public A(IA that) { this.a = that.a; this.ia = (ia as IDeepClone<IA>).DeepClone(); }
public IA DeepClone() { return new A(this); }
public IA ShallowClone() { return this.MemberwiseClone() as IA; }
}
public class B : A, IB
{ public double b { get; private set; }
public IB ib { get; private set; }
public B(IB that) : base(that) { this.b = that.b; this.ib = (ib as IDeepClone<IB>).DeepClone(); }
public new IB DeepClone() { return new B(this); }
public new IB ShallowClone() { return this.MemberwiseClone() as IB; }
}
Upvotes: 0
Reputation: 81149
I think I figured out a good use for iCloneable: to facilitate the creation of class hierarchies which include both cloneable and non-cloneable types.
If a class has a public Clone method, then it is impossible to derive from it a class which cannot be meaningfully cloned, without violating the Liskov Substitution Principle. The problem is that for any given class it may be useful to have both a version which is cloneable, and a version which allows non-cloneable derived classes. iCloneable provides a way to do this.
Suppose one wants to define the class hierarchy Widget, SuperWidget, and SuperDuperWidget, and SuperDuperNoncloneableWidget. Widget, SuperWidget, and SuperDuperWidget can each support cloning through protected method. One may derive from them classes CloneableWidget, CloneableSuperWidget, and CloneableSuperDuperWidget.
If one didn't use iCloneable (or something equivalent), it would be very difficult to write a function that would operate on a CloneableWidget, but could also operate on a CloneableSuperWidget. Using iCloneable, however, one can have one's function accept a Widget, and also require that it be iCloneable. This will thus allow one to work nicely within the desired hierarchy.
Note that unlike some other interfaces, iCloneable is not meaningful in isolation. It is only useful as a type constraint when applied to a class which may or may not publicly support cloning; the shallow/deep semantics will be those of that class.
Upvotes: 1
Reputation: 48949
Well, not much really. It earned a special mention in the Framework Design Guidelines as an interface to avoid.
Do not implement ICloneable. There are two general ways to implement ICloneable, either as a deep, or non-deep copy. Deep-copy copies the cloned object and all objects referenced by the object, recursively until all objects in the graph are copied. A non-deep copy (referred to as ‘shallow’ if only the top level references are copied) may do none, or part of a deep copy. Because the interface contract does not specify the type of clone performed, different classes have different implementations. A consumer cannot rely on ICloneable to let them know whether an object is deep-cloned or not.
There has been discussion in the past about obsoleting it. I am not sure what ever came of that, but the framework designers have admitted that it was probably a mistake.
If you want to support cloning then I would create and implement separate interfaces IDeepCopy
and IShallowCopy
or the like.
Upvotes: 33
Reputation: 11647
Create copy of specified object.
Supports cloning, which creates a new instance of a class with the same value as an existing instance.
EDIT: Scott Chamberlain absolutely right. This interface doesn't specified either this copy should be deep or shallow. And this is one of the most confusing thing about this interface.
Upvotes: 4
Reputation: 7803
From MSDN: "The ICloneable interface contains one member, Clone, which is intended to support cloning beyond that supplied by MemberwiseClone."
It is an interface that if implemented signals that instances of the class be cloned and not only shallow copied. Implementation of IClonable interface does not say anything about if it shallow copied or deep copied, though.
There is an interesting discussion about how to use IClonable here: http://channel9.msdn.com/forums/TechOff/202972-IClonable-deep-vs-shallow-best-practise/ .
Upvotes: 5