Looking for Clone() implementation with derived return Type

274 Views Asked by At

I am sure this must be a duplicate, but I can't find the answer:

If I have two classes:

public class BASE
{
    public BASE() {};
    public abstract BASE clone();
}


public class CHILD : BASE
{

    public CHILD() : base() {}
    public override BASE clone()
    {
        return new CHILD();
    }
}

I have to make an explicit conversion every time I want to clone an object of type CHILD like:

var a = new CHILD();
CHILD b = a.clone() as CHILD;

Is there a way to avoid this conversion? I would like to be able to write:

var original = new CHILD();
BASE copy1 = original.clone();
CHILD copy2 = original.clone();

Is this possible in C#?

3

There are 3 best solutions below

0
D Stanley On BEST ANSWER

Is there a way to avoid this conversion?

Not by overloading Clone - you can't overload a method just by changing its return type. Use a different method instead:

public class CHILD : BASE
{

    public CHILD() : base() {}
    public BASE clone() { return this.cloneChild();}
    public CHILD cloneChild()
    {
        return new CHILD();
    }
}

If you want to enforce that behavior on all inherited classes you could make BASE generic:

public abstract class BASE<T> where T:BASE<T>
{
    public BASE() {}
    public abstract T clone();
}


public class CHILD : BASE<CHILD>
{

    public CHILD() : base() {}
    public override CHILD clone()
    {
        return new CHILD();
    }
}
4
Ian On

If you need CHILD type instead of BASE type in the clone, then you need to do method hiding instead of method overriding. You should remove the override keyword and use new instead:

public class BASE
{
    public BASE() {};
    public abstract BASE clone();
}

public class CHILD : BASE
{

    public CHILD() : base() {}
    public new CHILD clone()
    {
        return new CHILD();
    }
}
0
x2bool On

C# does not support return type covariance. You can try this workaround (using generics):

public class Base<T> {
    public abstract T Clone()
}

public class Child : Base<Child> {
    public override Child Clone() {
        return ...;
    }
}