当涉及泛型时,如何将我的子类正确转换为其基类?

时间:2014-04-09 12:17:15

标签: c# generics inheritance polymorphism

我试图覆盖基本属性,如下所示:

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!

2 个答案:

答案 0 :(得分:4)

您无法执行此操作,因为NodeViewModel<T>在其类型参数T上不是covariantNodeViewModel<Node>不是&#34;基类&#34; NodeViewModel<SubNode>的{​​{1}},即使Node SubNode的基础。从技术上讲,这与继承无关。

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

答案 1 :(得分:2)

发生错误是因为您的NodeViewModel<T>类不协变。是否可以执行此操作取决于您需要支持的操作,但对于您的问题中的代码,您可以创建一个界面:

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>>();