C# – How to Restrict Method’s Parameter to the Class Where the Method Is Overridden

cdesignobject-oriented

I have quite simple class hierarchy:

public class Base
{
    //...
    public virtual void AssignFrom(Base baseObj)
    {
        //DoSomeStuff
    }
}
public class DerivedA : Base
{
    //...

    public override void AssignFrom(Base derivedObj)
    //Wish Method would be:
    //public override void AssignFrom(DerivedA derivedObj)
    {
        base.AssignFrom(derivedObj);
        var objAsDerivedA = derivedObj as DerivedA;
        //Some other stuff concerning derived class
    }
}
public class DerivedB : Base
    {
    //...

    public override void AssignFrom(Base derivedObj)
    //Wish Method would be:
    //public override void AssignFrom(DerivedB derivedObj)
    {
        base.AssignFrom(derivedObj);
        //Here I have to cast, what I would gladly avoid.
        var objAsDerivedB = derivedObj as DerivedB;
        //Some other stuff concerning derived class
    }
}

What bothers me is that each sibling of derived class or it's descendant can be used as parameter.

It would be possible to create own, non virtual method for each class, but in my opinion the association/connection between methods will be lost.

Question: Is there a way to restrict method's parameter to the class, where the method is overridden.

Best Answer

So you can do one level of inheritance with Generics. But a second layer fails essentially because you are attempting to remove the public AssignFrom method of the base class

public class Base
{
    public string MyProp { get; set; }
}

public class Base<T> : Base where T : Base
{
    //...
    public virtual void AssignFrom(T baseObj)
    {
        this.MyProp = baseObj.MyProp;
    }
}


public class DerivedA : Base<DerivedA>
{
    public string ExtraProp { get; set; }
    //...
    public override void AssignFrom(DerivedA derivedObj)
    {
        base.AssignFrom(baseObj);
        this.ExtraProp = baseObj.ExtraProp;
    }
}

public class DerivedB : Base<DerivedB>
{
    public override void AssignFrom(DerivedB derivedObj)
    {
        //this is fine
    }
}

public class DerivedB : DerivedA
{
    public override void AssignFrom(DerivedB derivedObj)
    {
        //this wont compile: no suitable method to override
    }
}

public class DerivedB : DerivedA, Base<DerivedB> //multiple inheritance not allowed!
{
    public override void AssignFrom(DerivedB derivedObj)
    {
    }
}

A generic interface can enforce the addition of an AssignFrom(DerivedB baseObj) method but not the removal of the base object's AssignFrom(DerivedA baseObj)

Essentially you would just be adding per class methods.

You will have to overcome your total addiction to Base.

The solution I feel is Copy Contstructors

public class Base
{
    public Base(Base baseObj) { }
}

public class DerivedA : Base
{
    public DerivedA(DerivedA derivedObj) : base(derivedObj) { }
}

public class DerivedB : DerivedA
{
    public DerivedB(DerivedB derivedObj) : base(derivedObj){ }
}

Now you can implement a constructor which sends something the the base class, but constructors are not inherited. So you don't have to remove the base classes constructor from your derived class