Is there a particular reason why a generic ICloneable<T>
does not exist?
It would be much more comfortable, if I would not need to cast it everytime I clone something.
Is there a particular reason why a generic ICloneable<T>
does not exist?
It would be much more comfortable, if I would not need to cast it everytime I clone something.
ICloneable is considered a bad API now, since it does not specify whether the result is a deep or a shallow copy. I think this is why they do not improve this interface.
You can probably do a typed cloning extension method, but I think it would require a different name since extension methods have less priority than original ones.
A big problem is that they could not restrict T to be the same class. Fore example what would prevent you from doing this:
They need a parameter restriction like:
I need to ask, what exactly would you do with the interface other than implement it? Interfaces are typically only useful when you cast to it (ie does this class support 'IBar'), or have parameters or setters that take it (ie i take an 'IBar'). With ICloneable - we went through the entire Framework and failed to find a single usage anywhere that was something other than an implementation of it. We've also failed to find any usage in the 'real world' that also does something other than implement it (in the ~60,000 apps that we have access to).
Now if you would just like to enforce a pattern that you want your 'cloneable' objects to implement, that's a completely fine usage - and go ahead. You can also decide on exactly what "cloning" means to you (ie deep or shallow). However, in that case, there's no need for us (the BCL) to define it. We only define abstractions in the BCL when there is a need to exchange instances typed as that abstraction between unrelated libraries.
David Kean (BCL Team)
I think the question "why" is needless. There is a lot of interfaces/classes/etc... which is very usefull, but is not part of .NET Frameworku base library.
But, mainly you can do it yourself.
Having read recently the article Why Copying an Object is a terrible thing to do?, I think this question needs additional clafirication. Other answers here provide good advices, but still the answer isn't complete - why no
ICloneable<T>
?Usage
So, you have a class that implements it. While previously you had a method that wanted
ICloneable
, it now has to be generic to acceptICloneable<T>
. You would need to edit it.Then, you could have got a method that checks if an object
is ICloneable
. What now? You can't dois ICloneable<>
and as you don't know the type of the object at compile-type, you can't make the method generic. First real problem.So you need to have both
ICloneable<T>
andICloneable
, the former implementing the latter. Thus an implementer would need to implement both methods -object Clone()
andT Clone()
. No, thanks, we already have enough fun withIEnumerable
.As already pointed out, there is also the complexity of inheritance. While covariance may seem to solve this problem, a derived type needs to implement
ICloneable<T>
of its own type, but there is already a method with the same signature (= parameters, basically) - theClone()
of the base class. Making your new clone method interface explicit is pointless, you will lose the advantage you sought when creatingICloneable<T>
. So add thenew
keyword. But don't forget that you would also need to override the base class'Clone()
(the implementation has to remain uniform for all derived classes, i.e. to return the same object from every clone method, so the base clone method has to bevirtual
)! But, unfortunately, you can't bothoverride
andnew
methods with the same signature. Choosing the first keyword, you'd lose the goal you wanted to have when addingICloneable<T>
. Chossing the second one, you'd break the interface itself, making methods that should do the same return different objects.Point
You want
ICloneable<T>
for comfort, but comfort is not what interfaces are designed for, their meaning is (in general OOP) to unify the behavior of objects (although in C#, it is limited to unifying the outer behavior, e.g. the methods and properties, not their workings).If the first reason hasn't convinced you yet, you could object that
ICloneable<T>
could also work restrictively, to limit the type returned from the clone method. However, nasty programmer can implementICloneable<T>
where T is not the type that is implementing it. So, to achieve your restriction, you can add a nice constraint to the generic parameter:public interface ICloneable<T> : ICloneable where T : ICloneable<T>
Certainly more restrictive that the one without
where
, you still can't restrict that T is the type that is implementing the interface (you can derive fromICloneable<T>
of different type that implements it).You see, even this purpose couldn't be achieved (the original
ICloneable
also fails at this, no interface can truly limit the behavior of the implementing class).As you can see, this proves making the generic interface is both hard to fully implement and also really unneeded and useless.
But back to the question, what you really seek is to have comfort when cloning an object. There are two ways to do it:
Additional methods
This solution provides both comfort and intended behavior to users, but it's also too long to implement. If we didn't want to have the "comfortable" method returning the current type, it is much more easy to have just
public virtual object Clone()
.So let's see the "ultimate" solution - what in C# is really intented to give us comfort?
Extension methods!
It's named Copy not to collide with the current Clone methods (compiler prefers the type's own declared methods over extension ones). The
class
constraint is there for speed (doesn't require null check etc.).I hope this clarifies the reason why not to make
ICloneable<T>
. However, it is recommended not to implementICloneable
at all.It's pretty easy to write the interface yourself if you need it: