Amazon.com Widgets

Implementing ICloneable

I was doing a little work on the Design Guidelines document tonight and I noticed this section that we added recently.   I thought I'd post it here for your comments.    Where are you using ICloneable today?  Do you agree with this suggestion?

 

1.1 Implementing ICloneable

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

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

Published 09 April 03 01:37 by BradA

Comments

# David Nicholson said on April 9, 2003 10:15 AM:
Well, I need copy functionality for my objects, so I implement ICloneable. However I write applications, not libraries, so my decision doesn't affect anyone else. It seemed obvious to me that the definition was loose, so I would be wary about calling Clone on something I didn't author. If I used a third party class I would consult the documentation, and would expect their implementation not to change in a breaking way. I'm not sure that everybody inventing their own equivalent helps much. I experience a similar confusion over Equals, but maybe that's just me.
# Mickey Williams said on April 9, 2003 2:09 PM:
Isn't (wasn't?) the point of ICloneable that the semantics are left to the type's author? You want a clone of my object - and I decide what being a clone is. Of course the problem with a weak contract is that given an arbitrary object reference, I can't discover the semantics of the implementation. The documentation doesn't help when you're discovering interfaces programmatically. IMO, It would be more helpful if there were two interfaces - one that implied shallow copies, and one that implied deep copies. In Eiffel, clone means shallow, and deep_clone is obvious.
# David Nicholson said on April 10, 2003 11:06 AM:
OK, forget the documentation! My problem with the author's decision is that I have cases where I really want a deep copy. I start with an object, create a copy, the user modify the copy, then I want to diff the two objects. So I want some interface to be deep_copy. I just find it frustrating that the only interface we have (although weak) is now considered a bad idea.
# kitg said on April 10, 2003 1:23 PM:
David, this is a great note. And the idea of two separate interfaces (shallow/deep) to track this is still a possibility. The problem is that a single interface, for which we didn't define the contract resulted in disparate implementations. The 'ICloneable' nature of an object tells you nothing about what the Clone does, meaning that accepting an ICloneable object (unless you can guarantee you know the contract of each object) is all but useless. If I then take that object and call Clone on it, what do I get? I have no idea. Too many valid implementations, with different definitions of the contract have shipped for us to justify enforcing a guideline at this point. Consider that if you did implement ICloneable, expecting all implementations to be deep, then if someone passes you a collection (such as ArrayList) you're in trouble.
# David Nicholson said on April 11, 2003 7:16 AM:
I guess the only thing you can closely define is a deep copy. This should mean that my new object contains _no_ references to the old one. As the guideline above points out, there are enless variations on a non-deep copy, so maybe a loose ICloneable would do for that. Then we need a new interface that is deep. Personally I think a clone that is anything other than shallow (i.e. a simple ref assignment) or deep (i.e. everything) is a nightmare. What use is a partial copy where the contained objects are copied or not based on the class author's choice?
# Chris Burrows said on April 19, 2003 7:25 AM:
I agree with Nick. I'm for one like to make things specific. Wouldn't it be better, rather than just using documentation to state what a method does actually use a name that describes what it is doing? If it’s a deep copy have a method called deepcopy (or something similar), if it’s not then call the method it shallowcopy. Copy in my opinion can be to easily miss interpreted. If a method describes what it is doing the better as it leads to easier understanding of what a program is doing.
# Frank Hileman said on August 5, 2003 7:16 PM:
It's a little too late to get rid of ICloneable now. It is implemented all over the Framework. I have used it once, to do a clone of every object in an array, but I could count on it only because I knew that every object was some primitive (int, double, etc). I always assumed the word "clone" meant "deep copy". This is what the convention has been in other languages and libraries.
# Pete said on September 8, 2003 10:27 AM:
The docs for Object.MemberwiseClone say that you should use ICloneable if a shallow copy is not appropriate. To me that is saying that ICloneable should be a deep copy.
# Kelly White said on July 6, 2007 12:34 PM:

As I&#39;ve mentioned earlier, I have a long commute to and from work each day. Each day as I ride the

# Angella Andrea Weblog said on October 20, 2008 3:50 PM:

Ho seguito il webcast &quot; Disegno Architetturale: gli idiomi e le linee guida di desing per il .NET

New Comments to this post are disabled

Search

Go

This Blog

Syndication

Page view tracker