简体   繁体   English

C#使用具体属性覆盖抽象属性

[英]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. A是b继承的抽象类。 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. 我正在使用mvc,由于动态类型存在一些问题,因此我无法说BaseClass<t> 。在其他一些领域中,调用名为GetHistory()方法的方法需要它返回具体列表而不是抽象列表。 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. A是B继承的抽象类。

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. 搜索协方差和协变,以了解这种转换在C#中是合法的,在C#中是非法的。 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#. 仅仅因为虚拟返回类型协方差从未在C#中实现,这是非法的。 It is implemented in C++. 它是用C ++实现的。

It hasn't been implemented because simply it's never been a high priority for the C# team. 它尚未实现,因为对于C#团队来说,从来就没有将它作为头等大事。 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. 如果您对此有强烈的兴趣,请加入github上的论坛并进行倡导。

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. 通过使具体类指定要使用的确切泛型(例如:基本类型),它可能适合您的目的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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