我想在C#中构建一个树结构,其中每个节点都是泛型类型T的包装器。但我需要树中的层次关系不与T的类型绑定.i。
Interface INode<T> : Where T: AbstractNodeContent{
T Value{get;set;}
IList<INode<AbstractNodeContent>> Children {get;set;}
INode<AbstractNodeContent> Parent {get;set;}
}
class abstract AbstractNodeContent{
}
class Region : AbstractNodeContent{
}
NodeRegion : INode<Region>{
// field
// contructor
INode<AbstractNodeContent> getRoot(){
return (i am root)? this : Parent.getRoot(); // compiler-error
}
}
我尝试了很多不同的解决方案,但我总是被困在这里,我无法弄清楚我失踪了什么。 问题是在上面的函数getRoot()中我不知道哪个类型是根节点所以我需要一个INode&lt; AbstractNodeContent&GT;作为回报函数,所以当我返回这个时我有一个编译器错误,说我不能从这个转换为INode&lt; AbstractNodeContent取代。
这是可以实现的结果还是我必须重新考虑设计?我喜欢有一种不同类型的树的想法。关于如何考虑这种类型的设计以及如何实现它,你能给出一些建议吗?
感谢。 Luca Colombini
答案 0 :(得分:1)
您之所以看到此原因,是因为您无法将Generic<SomeType>
隐式转换为Generic<ParentType>
。这是因为您有时会使用通用,有时会返回它,所以请参阅Contravariance and Covariance。
尝试制作INode类型的接口或抽象类,没有通用参数,因此您可以通过引用此父级来获得该类的“任何进展”版本。
public abstract class Node { }
public abstract class Node<T> : Node { ... }
这样,您的GetRoot可以返回一个简单的节点。
如果您想要更加安全,请在父类中包含internal abstract
成员,以便程序集之外的任何内容都不能实现非泛型父级。