我正在寻找/ tring在C#中实现类型安全树实现。
如何在不使用接口(强制在整个地方重新实现树功能)和不使用强制转换的情况下实现类型安全树?
我有使用树作为公共基类的想法,但是类型安全性已经消失。我目前的方法是使用泛型。但我错过了一些转换回基类型。
以下是简化/非工作示例。 这个想法是返回的节点支持树函数,同时它们也支持它们的基类型行为。 我可以在没有Node的情况下使用下面的类,但是然后我一方面放松了类型安全,并且还因为节点已经有了父类而导致继承问题。
我还玩弄了课程扩展,但我还没有得到任何接近可能解决方案的东西。
我想我需要一些关于如何继续的小提示。先谢谢你。
public class Node<T> // .
{
public Node<T> parent;
public List<Node<T>> children;
protected Node()
{
children = new List<Node<T>>();
parent = null;
}
protected Node(Node<T> parent)
: this()
{
this.parent = parent;
parent.addChildren(this);
}
protected void addChildren(Node<T> child)
{
children.Add(child);
}
public Node<T> getRoot() // returns root node
public List<Node<T>> flatten() // return 1d-list of all nodes.
}
答案 0 :(得分:0)
我有使用树作为公共基类的想法,但是类型安全性已经消失。我目前的方法是使用泛型。但我错过了一些转换回基类型。
然后将泛型类型约束为基类型:
public class Node<T> where T: BaseType { ... }
现在,只要Node<MyDerivedType>
派生自MyDerivedType
,您就可以创建BaseType
类型的任何树。
另一方面,我考虑在您的实施中修改以下内容:
Children
应该是一个属性,除非是readonly,否则不要公开字段。此外,您不应将其公开为List
;这将允许任何人直接添加或删除节点,这可能违反您的实现中假定的不变量。请改为IEnumerable<T>
:
private readonly List<T> children;
public IEnumerable<T> Children => children.Select(c => c);
您可以直接返回children
,因为它可以隐式转换为IEnumerable<T>
;问题是任何人都可以简单地将其强制转换回List<T>
并进行修改。投射它可以保护您免受此转换。
Flatten
也是如此(第一个 f 应该大写btw)。考虑返回IEnumerable<T>
。
答案 1 :(得分:0)
这是一个类型安全的树实现:
public class Tree<T> : List<Tree<T>>
{
public T Value { get; set; }
}
是的,就是这样。简单。
当然,您可以添加一个或两个构造函数,并使Value
属性为只读,以使其更友好。您可以轻松添加Parent
属性。