简体   繁体   中英

C# : Override a property and return a derived type

Let's say I have a class A with the property "Details" that return an instance of class B.

public class A
{
    public virtual B Details {get; set;}
}

Lets say also, I have a class Aext (A extended) that inherits from A. But I want that Aext.Details return an instance of class Bext (B extended) :

public class Aext : A
{
    public override Bext Details {get; set;}
}

This will not compile because the type Bext must match the type inherited from A.
Of course, I can easily solve that by just put B as return of Details for Aext.

public class Aext
{
    B Details {get; set;}
}

Assignment will work, but I'll have to check everytime I use an instance of Aext if Details is Bext or B.

Do you see a way of doing something cleaner that this solution ?

Thank you.

Maybe you can try generics, something like this:

public class A<T> where T : B
{
    public T Details { get; set; }
}

public class Aext : A<Bext>
{
}

public class B
{

}

public class Bext : B
{

}

If you need you can override T Details with Bext Details, it will work fine.

No - but I think therefore it indicates the base class is flawed in its design. You are trying to force Interface behaviours onto an Abstract class/method. The base method does nothing, do what exactly is being inherited ? The base class could have a protected member of type B accessed by each inheritor and exposed via their own strongly typed accessor method. The value would be available to all inheritors, but consumers would need to get/set a strongly typed version of the data.

If you do not want to introduce interfaces, you can do something like this:

public class B
{ }

public class Bext : B
{ }

public class A
{
    public virtual B Details { get; set; }

    public A()
    {
        Details = new B();
    }

}

public class Aext : A
{
    public override B Details => new Bext();
}

However, I would suggest you go with composition and use dependency injection, like this:

public interface IB
{ }
public class B : IB
{ }

public class Bext : IB
{ }

public class A
{
    public virtual IB Details { get; set; }

    public A(IB details)
    {
        Details = details;
    }
}

public class TestClass
{
    public void TestMethod()
    {
        IB details = new B();
        IB extDetails = new Bext();

        A instance1 = new A(details);
        A instance2 = new A(extDetails);
    }
}

This way, you do not need to extend the inheritance hierarchy by creating Aext class. You can contain that strictly to the properties in question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM