268

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.

4
  • 7
    No! with all due respect to the 'reasons', I agree with you, they should have implemented it! Commented Jan 13, 2010 at 0:53
  • It would have been a nice thing for Microsoft to have defined (the problem with brew-your-own interfaces is that interfaces in two different assemblies will be incompatible, even if they're semantically identical). Were I designing the interface, it would have three members, Clone, Self, and CloneIfMutable, all of which would return a T (the last member would either return Clone or Self, as appropriate). The Self member would make it possible to accept an ICloneable(of Foo) as a parameter and then use it as a Foo, without need for a typecast.
    – supercat
    Commented Jan 12, 2011 at 17:17
  • That would allow for a proper cloning class hierarchy, where inheritable classes expose a protected "clone" method, and have sealed derivatives that expose a public one. For example, one could have Pile, CloneablePile:Pile, EnhancedPile:Pile, and CloneableEnhancedPile:EnhancedPile, none of which would be broken if cloned (even though not all expose a public cloning method), and FurtherEnhancedPile:EnhancedPile (which would be broken if cloned, but doesn't expose any cloning method). A routine that accepts an ICloneable(of Pile) could accept a CloneablePile or a CloneableEnhancedPile...
    – supercat
    Commented Jan 12, 2011 at 17:26
  • ...even though CloneableEnhancedPile does not inherit from CloneablePile. Note that if EnhancedPile inherited from CloneablePile, FurtherEnhancedPile would have to expose a public cloning method and could be passed to code that would expect to Clone it, violating the Liskov Substitutability Principle. Since CloneableEnhancedPile would implement ICloneable(Of EnhancedPile) and by implication ICloneable(Of Pile), it could be passed to a routine expecting a cloneable derivative of Pile.
    – supercat
    Commented Jan 12, 2011 at 17:30

8 Answers 8

158

In addition to Andrey's reply (which I agree with, +1) - when ICloneable is done, you can also choose explicit implementation to make the public Clone() return a typed object:

public Foo Clone() { /* your code */ }
object ICloneable.Clone() {return Clone();}

Of course there is a second issue with a generic ICloneable<T> - inheritance.

If I have:

public class Foo {}
public class Bar : Foo {}

And I implemented ICloneable<T>, then do I implement ICloneable<Foo>? ICloneable<Bar>? You quickly start implementing a lot of identical interfaces... Compare to a cast... and is it really so bad?

11
  • 13
    +1 I always thought that the covariance problem was the real reason Commented Feb 11, 2009 at 11:31
  • There is a problem with this: the explicit interface implementation must be private, which would cause problems should Foo at some point need to be cast to ICloneable... Am I missing something here? Commented Mar 26, 2009 at 10:33
  • 3
    My mistake: it turns out that, despite being defined as private, the method will be called should Foo be cast to IClonable (CLR via C# 2nd Ed, p.319). Seems like an odd design decision, but there it is. So Foo.Clone() gives the first method, and ((ICloneable) Foo).Clone() gives the second method. Commented Mar 26, 2009 at 12:51
  • 1
    Actually, explicit interface implementations are, strictly speaking, part of the public API. In that they are callable publicly via casting. Commented Mar 26, 2009 at 12:58
  • 9
    The proposed solution seems great at first... until you realize that in a class hierarchy, you want 'public Foo Clone()' to be virtual and overridden in derived classes so they can return their own type (and clone their own fields of course). Sadly, you can't change the return type in an override (the covariance problem mentioned). So, you come full circle back to the original problem again - the explicit implementation doesn't really buy you much (other than returning the base type of your hierarchy instead of 'object'), and you're back to casting most of your Clone() call results. Yuck! Commented Apr 23, 2012 at 3:11
127

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.

19
  • 13
    I disagree, bad or not bad, it's very useful sometime for SHALLOW clonning, and in those cases is really needed the Clone<T>, to save an unnecessary boxing and unboxing. Commented Jan 13, 2010 at 0:51
  • 2
    @AndreyShchekin: What's unclear about deep vs shallow cloning? If List<T> had a clone method, I would expect it to yield a List<T> whose items have the same identities as those in the original list, but I would expect that any internal data structures would be duplicated as needed to ensure that nothing done to one list will affect the identities of items stored in the other. Where's the ambiguity? A bigger problem with cloning comes with a variation of the "diamond problem": if CloneableFoo inherits from [not publicly cloneable] Foo, should CloneableDerivedFoo derive from...
    – supercat
    Commented Aug 10, 2012 at 15:26
  • 5
    @supercat: I can not say I understand your expectation fully, as what will you consider an identity of the list itself, for example (in case of list of lists)? However, ignoring that, your expectation is not the only possible idea people may have when calling or implementing Clone. What if library authors implementing some other list do not follow your expectation? The API should be trivially unambiguous, not arguably unambiguous. Commented Aug 11, 2012 at 1:11
  • 4
    @supercat So you are talking about shallow copy. However, there is nothing fundamentally wrong with a deep copy, for example if you want to do a reversible transaction on in-memory objects. Your expectation is based on your use case, other people may have different expectations. If they put your objects into their objects (or vice versa), results will be unexpected. Commented Aug 13, 2012 at 22:23
  • 8
    @supercat you do not take into account it is a part of .NET framework, not part of your application. so if you make a class that does not do deep cloning, then someone else makes a class that does do deep cloning and calls Clone on all its parts, it will not work predictably -- depending on whether that part was implemented by you or that person who likes deep cloning. your point about the patterns is valid but having IMHO in API is not clear enough -- it either should be called ShallowCopy to stress the point, or not provided at all. Commented Aug 14, 2012 at 0:36
20

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)

13
  • 2
    Non-generic ICloneable isn't very useful, but ICloneable<out T> could be quite useful if it inherited from ISelf<out T>, with a single method Self of type T. One doesn't often need "something that's cloneable", but one may very well need a T that's cloneable. If a cloneable object implements ISelf<itsOwnType>, a routine that needs a T that's cloneable can accept a parameter of type ICloneable<T>, even if not all of the cloneable derivatives of T share a common ancestor.
    – supercat
    Commented Mar 1, 2012 at 0:30
  • Thanks. That's similar to cast situation I mentioned above (ie 'does this class support 'IBar'). Sadly, we've only come up with very limited and isolated scenarios where you would actually make use of the fact that T is cloneable. Do you have situations in mind?
    – David Kean
    Commented Mar 1, 2012 at 3:57
  • One thing that's sometimes awkward in .net is managing mutable collections when the contents of a collection are supposed to be viewed as a value (i.e. I will want to know later the set of items that are in the collection now). Something like ICloneable<T> could be useful for that, though a broader framework for maintaining parallel mutable and immutable classes might be more helpful. In other words, code which needs to see what some type of Foo contains but is neither going to mutate it nor expect that it won't ever change could use an IReadableFoo, while...
    – supercat
    Commented Mar 1, 2012 at 5:18
  • ...code which wants to hold the contents of Foo could use an ImmutableFoo while code that to wants to manipulate it could use a MutableFoo. Code given any type of IReadableFoo should be able to get either a mutable or immutable version. Such a framework would be nice, but unfortunately I can't find any nice way to set things up in a generic fashion. If there were a consistent way to make a read-only wrapper for a class, such a thing could be used in combination with ICloneable<T> to make an immutable copy of a class which holds T'.
    – supercat
    Commented Mar 1, 2012 at 5:24
  • @supercat If you're wanting to clone a List<T>, such that the cloned List<T> is a new collection holding pointers to all of the same objects in the original collection, there are two easy ways of doing that without ICloneable<T>. The first is the Enumerable.ToList() extension method: List<foo> clone = original.ToList(); The second is the List<T> constructor that takes an IEnumerable<T>: List<foo> clone = new List<foo>(original); I suspect the extension method is probably just calling the constructor, but both of these will do what you're requesting. ;)
    – CptRobby
    Commented Oct 3, 2013 at 17:54
14

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.

public interface ICloneable<T> : ICloneable {
    new T Clone();
}

public abstract class CloneableBase<T> : ICloneable<T> where T : CloneableBase<T> {
    public abstract T Clone();
    object ICloneable.Clone() => return this.Clone();
}

public abstract class CloneableExBase<T> : CloneableBase<T> where T : CloneableExBase<T> {
    protected abstract T CreateClone();
    protected abstract void FillClone(T clone);
    public override T Clone() {
        T clone = this.CreateClone();
        if (clone is null ) {
            throw new NullReferenceException( "Clone was not created." );
        }

        this.FillClone(clone);
        return clone
    }
}

public abstract class PersonBase<T> : CloneableExBase<T> where T : PersonBase<T> {
    public string Name { get; set; }

    protected override void FillClone( T clone ) {
        clone.Name = this.Name;
    }
}

public sealed class Person : PersonBase<Person> {
    protected override Person CreateClone() => return new Person();
}

public abstract class EmployeeBase<T> : PersonBase<T> where T : EmployeeBase<T> {
    public string Department { get; set; }

    protected override void FillClone(T clone) {
        base.FillClone(clone);

        clone.Department = this.Department;
    }
}

public sealed class Employee : EmployeeBase<Employee> {
    protected override Employee CreateClone() => return new Employee();
}
4
  • 1
    Any workable clone method for an inheritable class must use Object.MemberwiseClone as a starting point (or else use reflection) since otherwise there's no guarantee that the clone will be the same type as the original object. I have a pretty nice pattern if you're interested.
    – supercat
    Commented Oct 22, 2010 at 22:25
  • @supercat why not make it an answer then?
    – nawfal
    Commented Apr 17, 2013 at 19:25
  • "There is a lot of interfaces/classes/etc... which is very usefull, but is not part of .NET Frameworku base library." Can you give us examples?
    – Krythic
    Commented Dec 25, 2016 at 1:52
  • 4
    @Krythic i.e.: advanced datastructures like b-tree, red-black tree, circle buffer. In '09 there was no tuples, generic weak-reference, concurrent collections ...
    – TcKs
    Commented Dec 26, 2016 at 16:14
12

It's pretty easy to write the interface yourself if you need it:

public interface ICloneable<T> : ICloneable
        where T : ICloneable<T>
{
    new T Clone();
}
5
  • I included a snippet since because of the honor of the copy-rights the link was broken... Commented Jan 12, 2010 at 16:37
  • 2
    And how exactly is that interface supposed to work? For the result of a clone operation to be castable to type T, the object being cloned has to derive from T. There's no way to set up such a type constraint. Realistically speaking, the only thing I can see the result of iCloneable returning is a type iCloneable.
    – supercat
    Commented Oct 16, 2010 at 22:17
  • @supercat: yes, that's exactly what Clone() returns: a T which implements ICloneable<T>. MbUnit has been using this interface for years, so yes, it works. As for the implementation, take a peek into MbUnit's source. Commented Oct 17, 2010 at 2:14
  • 2
    @Mauricio Scheffer: I see what's going on. No type actually implements iCloneable(of T). Instead, each type implements iCloneable(of itself). That would work, I guess, though all it does is move a typecast. It's too bad there's no way to declare a field as having an inheritance constraint and an interface one; it would be helpful to have a cloning method return an object of a semi-cloneable (cloning exposed as Protected method only) base type, but with a cloneable type constraint. That would allow an object to accept cloneable derivatives of semi-cloneable derivatives of a base type.
    – supercat
    Commented Oct 17, 2010 at 15:25
  • @Mauricio Scheffer: BTW, I would suggest that ICloneable(of T) also support a readonly Self property (of return type T). This would allow a method to accept an ICloneable(of Foo) and use it (via the Self property) as a Foo.
    – supercat
    Commented Dec 1, 2010 at 0:56
12

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>?

  1. 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 accept ICloneable<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 do is 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> and ICloneable, the former implementing the latter. Thus an implementer would need to implement both methods - object Clone() and T Clone(). No, thanks, we already have enough fun with IEnumerable.

    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) - the Clone() of the base class. Making your new clone method interface explicit is pointless, you will lose the advantage you sought when creating ICloneable<T>. So add the new 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 be virtual)! But, unfortunately, you can't both override and new methods with the same signature. Choosing the first keyword, you'd lose the goal you wanted to have when adding ICloneable<T>. Chossing the second one, you'd break the interface itself, making methods that should do the same return different objects.

  2. 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 implement ICloneable<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 from ICloneable<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

public class Base : ICloneable
{
    public Base Clone()
    {
        return this.CloneImpl() as Base;
    }

    object ICloneable.Clone()
    {
        return this.CloneImpl();
    }

    protected virtual object CloneImpl()
    {
        return new Base();
    }
}

public class Derived : Base
{
    public new Derived Clone()
    {
        return this.CloneImpl() as Derived;
    }

    protected override object CloneImpl()
    {
        return new Derived();
    }
}

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!

public class Base : ICloneable
{
    public virtual object Clone()
    {
        return new Base();
    }
}

public class Derived : Base
{
    public override object Clone()
    {
        return new Derived();
    }
}

public static T Copy<T>(this T obj) where T : class, ICloneable
{
    return obj.Clone() as T;
}

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 implement ICloneable at all.

2
  • Appendix #1: The only possible usage of a generic ICloneable is for value types, where it could circumvent the boxing of the Clone method, and it implies you have the value unboxed. And as structures can be cloned (shallowly) automatically, there is no need to implement it (unless you make it specific that it means deep copy).
    – IS4
    Commented Nov 12, 2014 at 20:00
  • The extension method is genious! Commented Jul 21, 2023 at 18:49
2

A big problem is that they could not restrict T to be the same class. Fore example what would prevent you from doing this:

interface IClonable<T>
{
    T Clone();
}

class Dog : IClonable<JackRabbit>
{
    //not what you would expect, but possible
    JackRabbit Clone()
    {
        return new JackRabbit();
    }

}

They need a parameter restriction like:

interfact IClonable<T> where T : implementing_type
5
  • 12
    That doesn't seem as bad as class A : ICloneable { public object Clone() { return 1; } /* I can return whatever I want */ } Commented Jul 27, 2012 at 20:23
  • 2
    I don't really see what the problem is. No interface can force implementations to behave reasonably. Even if ICloneable<T> could constrain T to match its own type, that wouldn't force an implementation of Clone() to return anything remotely resembling the object upon which it was cloned. Further, I would suggest that if one is using interface covariance, it may be best to have classes which implement ICloneable be sealed, have the interface ICloneable<out T> include a Self property which is expected to return itself, and...
    – supercat
    Commented Aug 27, 2012 at 16:40
  • ...have consumers cast or constrain to ICloneable<BaseType> or ICloneable<ICloneable<BaseType>>. The BaseType in question should have a protected method for cloning, which would be called by the type which implements ICloneable. This design would allow for the possibility that one might wish to have a Container, a CloneableContainer, a FancyContainer, and a CloneableFancyContainer, the latter being usable in code which requires a cloneable derivative of Container or which requires a FancyContainer (but doesn't care if it's cloneable).
    – supercat
    Commented Aug 27, 2012 at 16:45
  • The reason I'd favor such a design is that the issue of whether a type can be cloned sensibly is somewhat orthogonal to other aspects of it. For example, one might have a FancyList type which could be cloned sensibly, but a derivative might automatically persist its state in a disk file (specified in the constructor). The derived type couldn't be cloned, because its state would be attached to that of a mutable singleton (the file), but that shouldn't preclude use of the derived type in places which need most features of a FancyList but wouldn't need to clone it.
    – supercat
    Commented Aug 27, 2012 at 16:56
  • +1 - this answer is the only one from those I've seen here that really answers the question.
    – IS4
    Commented Nov 12, 2014 at 18:12
0

It's a very good question... You could make your own, though:

interface ICloneable<T> : ICloneable
{
  new T Clone ( );
}

Andrey says it's considered a bad API, but i have not heard anything about this interface becoming deprecated. And that would break tons of interfaces... The Clone method should perform a shallow copy. If the object also provides deep copy, an overloaded Clone ( bool deep ) can be used.

EDIT: Pattern i use for "cloning" an object, is passing a prototype in the constructor.

class C
{
  public C ( C prototype )
  {
    ...
  }
}

This removes any potential redundant code implementation situations. BTW, talking about the limitations of ICloneable, isn't it really up to the object itself to decide whether a shallow clone or deep clone, or even a partly shallow/partly deep clone, should be performed? Should we really care, as long as the object works as intended? In some occasions, a good Clone implementation might very well include both shallow and deep cloning.

3
  • "bad" does not mean deprecated. It simply mean "you're better off not using it". It's not deprecated in the sense that "we'll remove the ICloneable interface in the future". They just encourage you not to use it, and won't update it with generics or other new features. Commented Feb 11, 2009 at 11:22
  • Dennis: See Marc's answers. Covariance / inheritance issues make this interface pretty much unusable for any scenario that is at least marginally complicated. Commented Feb 11, 2009 at 11:33
  • Yea, i can see the limitations of ICloneable, for sure... I rarely need to use cloning, though.
    – baretta
    Commented Feb 11, 2009 at 12:07

Not the answer you're looking for? Browse other questions tagged or ask your own question.