Should we Obsolete ICloneable (The SLAR on System.ICloneable)

I decided to jump ahead a bit on my series on sharing some of the information in the .NET Framework Standard Library Annotated Reference Vol 1. This week the BCL team spent some time thinking about whether or not we should obsolete the ICloneable and I thought I’d let you folks participate in that debate.

The Background…

From the Design Guidelines:

The ICloneable interface contains a single Clone method, which is used to create a copy of the current object.

public interface ICloneable {

       object Clone();

}

Do not implement ICloneable[1].

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.

Note: If you need a cloning mechanism, define your own Clone, or Copy methodology, and ensure that you document clearly whether it is a deep or shallow copy. An appropriate pattern is:

public <type> Copy();

 

Do not use ICloneable in public APIs

From the .NET Framework Standard Library Annotated Reference Vol 1:

JR The documentation for this interface states that Clone can make either a shallow

or deep copy. This is ridiculous; the standard should have defined Clone as making

a deep copy. Without a guarantee of the type of copy, you must be careful how you

use a cloned object and have intimate knowledge of what Clone does for a type; this

information is usually not documented, leading to problems.

KG Echoing Jeffrey’s comment, without a contract for ICloneable, which speci-

fies whether it is deep or shallow, this interface is close to unusable. Defining a deepcopy

version would have definitely been the most useful approach here.

Because of this loose contract, anyone utilizing the ICloneable aspect of a class

really has no idea what he or she can then do with the class. Users can’t assume that

it’s a tearaway version (the result of a deep copy), because if they manipulate the

resulting “Clone” at all, then they may also be affecting the original. This may have

unwanted side effects.

Unfortunately, the disparate implementations of this interface throughout the framework

make it next to impossible to fix at this stage. You can just define a Copy method

on classes in order to support your own deep-cloning; however, I do urge caution

since this can be very difficult to guarantee. As soon as you have a reference to something

which does not itself define a deep-clone mechanism, you cannot successfully

The Debate

The arguments in favor of obsoleting ICloneable include:

1. Obsoleting it will help us clean-up our mistake

2. Obsoleting is much stronger than the design guideline and FxCop rule we have

3. Obsoleting makes it more clear the developers using the framework what the issues are with this type

The argument against obsoleting ICloneable include:

1. Developers could define a strong contract for ICloneable on their types thereby making this a useful interface.

2. The Design Guidelines rules and FxCop are good enough form of education on this issue

3. We should not obsolete this ICloneable until we have a replacement design that will work better.

As always, I’d love to hear your comments, concerns, thoughts on this issue…