简体   繁体   中英

C# Override abstract property with concrete property

So I have this abstract class. Which has a list of abstract types

public abstract class BaseClass
{

    public abstract List<A> History { get; set; }

and the inheritor class.

public class ConcreteClass : BaseClass
{
    public override List<B> History { get; set; }

My question is simple. Why does this return an error. A is an abstract class that b inherits. So why can't I have a concrete property override an abstract property?

Note:Due to other issues I cannot use generics with the base class. Some clarity on the issue. I am using mvc and due to some problems with dynamic types I cannot say BaseClass<t> And in some other areas methods that call a method called GetHistory() need it to return the concrete list not the abstract list. So I am stuck between a rock and a hard place.

Why does this return an error. A is an abstract class that B inherits.

Once again. This question is asked pretty much every day.

abstract class Fruit 
{
  public virtual List<Fruit> M() { return new List<Fruit>(); }
}
class Apple : Fruit
{
  public override List<Apple> M() { return new List<Apple>(); }
}

Suppose that was legal. What goes wrong?

class Banana : Fruit { }

...

Fruit f = new Apple(); // Legal
List<Fruit> bowl = f.M(); // calls Apple.M, returns a list of apples.
bowl.Add(new Banana());

And now there is a banana in a bowl that may only contain apples.

That's why this has to be illegal. Do a search for covariance and contravariance to learn when this kind of conversion is legal in C# and when it is illegal. Briefly, it is legal only when the compiler can prove that it is safe, and when the type arguments are reference types .

Now, what about this?

abstract class Fruit 
{
  public virtual Fruit N() { return new Banana(); }
}
class Apple : Fruit {
  public override Apple N() { return new Apple(); }
}
...
Fruit f1 = new Apple();
Fruit f2 = f1.N(); // No problem, an apple is a fruit.

This doesn't wreck the type system; this would be safe but it is still illegal. It's illegal simply because virtual return type covariance has never been implemented in C#. It is implemented in C++.

It hasn't been implemented because simply it's never been a high priority for the C# team. People have been asking for it for over a decade, but it's just not a great feature. Maybe it will get done eventually; if you feel strongly about it, join the forum on github and advocate for it.

One approach you could consider is:

public class ConcreteClass : BaseClass<ListClass>
{
    public override List<ListClass> History { get; set; }
}

public abstract class BaseClass<T> where T : BaseListClass
{
    public abstract List<T> History { get; set; }
}

public abstract class BaseListClass
{
}

public class ListClass : BaseListClass
{
}

By making the concrete class specify the exact generic type it wants to use (re: the base type) then it may suit your purposes.

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