How to override method with derived return type in C#?

六月ゝ 毕业季﹏ 提交于 2019-12-02 11:46:52

You could make the base class generic:

public abstract class Base<TDerived> where TDerived : Base {
  public abstract TDerived Clone();
}

public class Derived1 : Base<Derived1> {
  public override Derived1 Clone() { ... }
}

public class Derived2 : Base<Derived2> {
  public override Derived2 Clone() { ... }
}

However this makes me wonder how useful having a common base class is. Perhaps the Clone implementations of Derived1 and Derived2 don't need to be part of a common interface.

The new keyword implicitly 'overrides' the base functionality anyway. Unless for some reason you specifically want override to appear in code, then a single new modifier will suffice. I would also explore abstrating the clone functionality into an interface, it allows you to make more assumptions in code, at a later date.

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

public class A1 : ICloneable<A1>
{
    public int X1 { get; set; }
    public A1(int x1) { this.X1 = x1; }

    public virtual A1 Clone()
    {
        return new A1(X1);
    }
}
public class A2 : A1, ICloneable<A2>
{
    public int X2 { get; set; }

    public A2(int x1, int x2)
        : base(x1)
    {
        this.X2 = x2;
    }

    public virtual new A2 Clone()
    {
        return new A2(X1, X2);
    }
}

public class A3 : A2, ICloneable<A3>
{
    public int X3 { get; set; }

    public A3(int x1, int x2, int x3)
        : base(x1, x2)
    {
        this.X3 = x3;
    }

    public virtual new A3 Clone()
    {
        return new A3(X1, X2, X3);
    }
}

EDIT: The resultant possible behaviour:

public class A4 : A3, ICloneable<A4>
{
    public int X4 { get; set; }

    public A4(int x1, int x2, int x3, int x4)
        : base(x1, x2, x3)
    {
        this.X4 = x4;
    }

    public override A3 Clone()
    {
        return ((ICloneable<A4>)this).Clone();
    }

    A4 ICloneable<A4>.Clone()
    {
        return new A4(X1, X2, X3, X4);
    }
}

I'd advise against all of this. Just stick to the standard interfaces and patterns for such things. Implement System.ICloneable...

http://msdn.microsoft.com/en-us/library/system.icloneable(v=vs.110).aspx

Object Clone()

Simple no?

If you must deviate, I would use generics as Andrew Kennan has suggested. However I would still implement System.ICloneable as it makes the class more inter-operable with other frameworks.

In addition ICloneable should be implemented using a protected constructor e.g.

public class A1 : ICloneable
{
    public A1(int x1) { this.X1 = x1; }
    protected A1(A1 copy) { this.X1 = copy.X1; }

    public int X1 { get; set; }

    public virtual object Clone()
    {
        return new A1(this); // Protected copy constructor
    }
}

This way you can inherit A1 as such...

public class B1 : A1, ICloneable
{
    public B1(int x1, int y1) : base(x1) { this.Y1 = y1; }
    protected B1(B1 copy) : base(copy) { this.Y1 = copy.Y1; }

    public int Y1 { get; set; }

    public virtual object Clone()
    {
        return new B1(this); // Protected copy constructor
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!