Search code examples
c#inheritanceoverridingclonecloning

How to inherit cloning methods properly?


I have a base class (A) and a delivered one (B). They inherit the ICloneable<> generic interface that I made:

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

I would like to override the A.Clone() method in B but so, that B.Clone() returns an object of type B instead of A, however, overriding does not allow that.

I have some kind of workaround, but I find it really ugly:

class A : ICloneable<A>
{
    virtual A Clone() => /*magic*/;
}
class B : A, ICloneable<B>
{
    B CloneAsB() => /*other kind of magic*/;
    override A Clone() => CloneAsB();
}

(I also added explicit implementation of the non-generic ICloneable, but did not show it in the example.)

Is there a better way to achieve this, without having to have a false clone method?


Solution

  • I found a better workaround: passing the call of the generic ICloneable<A>.Clone() method down the inheritance hierarchy using the non-generic ICloneable.Clone() might be useful, as shown here:

    class A : ICloneable<A>, ICloneable
    {
        A Clone() => (A) ((ICloneable) this).Clone(); //This will call ICloneable.Clone in class B if the type of the object is B!
    
        //If object is of type B, not this but the derived method is called:
        object ICloneable.Clone() => /*Cloning, if object is an instance of A*/;
    }
    class B : A, ICloneable<B>
    {
        new B Clone() => (B) ((ICloneable) this).Clone(); //This will call ICloneable.Clone in a derived type if object is of more derived type!
    
        //If object is of even more derived type, not this but the method of the derived class is called:
        object ICloneable.Clone() => /*Cloning, if object is an instance of B*/;
    }
    //Same implementation for class C...
    

    This has the advantage that none of the methods have to explicitly check for the type of the object (i.e. in class A, Clone() does not have to check if the object is of type B).