【问题标题】:How do I convert my subclass to its base class properly when generics are involved?当涉及泛型时,如何正确地将我的子类转换为其基类?
【发布时间】:2014-04-09 12:17:14
【问题描述】:

我正在尝试像这样覆盖基本属性:

public class Node {}
public class SubNode : Node { }

public class NodeViewModel<T> where T : Node
{
    public virtual T Data { get; set; }
}
public class SubNodeViewModel : NodeViewModel<SubNode>
{
    public override SubNode Data { get; set; }
}

...
List<NodeViewModel<Node>> l = new List<NodeViewModel<Node>>();
l.Add(new SubNodeViewModel()); // Cannot convert from SubNodeViewModel to NodeViewModel<Node>
...

我想我一定是误解了继承的基本原理。为什么我不能这样做?

我想我对为什么会这样感到困惑:

Node node;
SubNode subnode;
node = subnode; // I work just fine!

但不是这个:

NodeViewModel<Node> node;
SubNodeViewModel subnode;
node = subnode; // I don't work. Also, I hate you!

【问题讨论】:

  • 只要删除public override SubNode Data { get; set; },你就会得到你想要的。

标签: c# generics inheritance polymorphism


【解决方案1】:

您不能这样做,因为NodeViewModel&lt;T&gt; 在其类型参数T 上不是covariantNodeViewModel&lt;Node&gt; 不是NodeViewModel&lt;SubNode&gt; 的“基类”,即使Node SubNode 的基础。从技术上讲,这与继承无关。

如果您想在同一个列表中包含各种 NodeViewModel,唯一的方法是使用公共接口或基类作为列表的类型参数。

【讨论】:

  • 感谢+1的解释和建议。
【解决方案2】:

发生错误是因为您的 NodeViewModel&lt;T&gt; 类不是协变的。能否做到这一点取决于你需要支持的操作,但是对于你问题中的代码你可以创建一个接口:

public interface INodeViewModel<out T> where T : Node
{
    T Data { get; }
}

然后实现它

public NodeViewModel<T> : INodeViewModel<T> where T : Node { ... }

然后更改l中的项目类型:

List<INodeViewModel<Node>> l = new List<INodeViewModel<Node>>();

【讨论】:

  • 谢谢,界面运行良好 - 快速代码 sn-p 很有帮助。
猜你喜欢
  • 2014-11-05
  • 2019-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多