• 11
• 9
• 10
• 9
• 10

# [.net] No ICloneableT?

This topic is 3551 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Why is there no ICloneable<T> only ICloneable? Is there any way to specify the type so there is no need to box and unbox when I make a copy of the object?

##### Share on other sites
Nope, no ICloneable<T> (heaven only knows why). The common solution is as follows:

class MyClass : ICloneable{    public MyClass Clone()    {        // do the clone stuff here        return myClone;    }    object ICloneable.Clone()    {        return Clone();    }}

##### Share on other sites
I think it's a really good question why there's no ICloneable<T>, as it wouldn't have been too much work to incorporate it into the framework. I think MS did it intentionally because it is nearly inpossible to define what "cloning" really means. By not providing ICloneable<T> MS wanted to avoid people to use the misleading concept of "cloning" I guess. I wrote an article on my blog if you're interested: http://blog.andreloker.de/post/2008/07/30/How-deep-is-your-clone.aspx

##### Share on other sites
ICloneable, in my opinion, was just a poor idea from the start. Like VizOne said, its hard to define what exactly is a clone. Does it make a new deep copy of the object? If so, does it make a deep copy of objects it references? Just ones that also implement ICloneable? In the end, you can't be sure what anything is.

Btw, unless I'm horribly mistaken, boxing only applies to value types. The only penalties you face here would be casting from object to MyClass, and less strict typing (though why anyone would try to cast a Clone() to something other than what they cloned is beyond me).

##### Share on other sites
Quote:
 Original post by SpodiBtw, unless I'm horribly mistaken, boxing only applies to value types.
You're correct. Boxing only applies to value types.

Quote:
 Original post by SpodiICloneable, in my opinion, was just a poor idea from the start. Like VizOne said, its hard to define what exactly is a clone. Does it make a new deep copy of the object? If so, does it make a deep copy of objects it references? Just ones that also implement ICloneable? In the end, you can't be sure what anything is.
It's another method that a developer can use to define the behavior of his or her objects. Flexibility is key. Two things should be assumed: 1) If an object implements ICloneable then the original developer made a conscious decision and the interface is defined appropriately; 2) that if you choose to implement the interface you should perform a copy - deep or shallow, as appropriate - for all of your type's members.

Another way to look at this is to think about an object and what constitutes the identity of an object, or what data shouldn't be shared between object instances because it should be freely mutable. Using ICloneable you define which properties should be deep copied and which should be shallow copied. That's also where there's no generic version - a true deep copy of an entire object graph is a tremendous amount of work and in 99.999% of the situations it would occur in that deep copy wouldn't be necessary.

So, yes, ICloneable's implementation depends upon the type's author. Unless you have reason to dispute his knowledge or ability, however, you should assume it performs a copy just deep enough for an object to be cloned and subsequently manipulated without adversely affecting the original object.

##### Share on other sites
Even if having a clone-interface would be a good idea, would a generic ICloneable<T> really solve more problems than it would create?

I assume you'd like the Clone() method of class A to return an object of the same type A? In the context of inheritance, a generic ICloneable wouldn't really help AFAIK, as you'd have to re-implement the interface in each subclass, and you'd have to deal with the base classes' implementations (rerouting them to your most updated Clone() method). I'd say you want covariant return types, and generics are not really the way to go for that.

Using new as shown by Mike.Popoloski looks to me to be the most straightforward solution in C# as it is now.