Ищем реализацию Clone() с производным типом возврата

Я уверен, что это должен быть дубликат, но я не могу найти ответ:

Если у меня есть два класса:

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


public class CHILD : BASE
{

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

Я должен делать явное преобразование каждый раз, когда хочу клонировать объект типа CHILD, например:

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

Есть ли способ избежать этого преобразования? Я хотел бы иметь возможность написать:

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

Возможно ли это в C#?

3 ответа

Есть ли способ избежать этого преобразования?

Не перегружая Clone - вы не можете перегрузить метод, просто изменив его тип возвращаемого значения. Вместо этого используйте другой метод:

public class CHILD : BASE
{

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

Если вы хотите применить это поведение ко всем унаследованным классам, вы можете сделать BASE общий:

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();
    }
}

Если тебе надо CHILD тип вместо BASE введите в clone, тогда вам нужно сделать скрытие метода вместо переопределения метода. Вы должны удалить override ключевое слово и использование new вместо:

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

public class CHILD : BASE
{

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

C# не поддерживает ковариацию возвращаемого типа. Вы можете попробовать этот обходной путь (используя дженерики):

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

public class Child : Base<Child> {
    public override Child Clone() {
        return ...;
    }
}
Другие вопросы по тегам