在c#中实现类型安全树(类型安全节点)



我正在寻找/尝试在c#中实现类型安全树。

如何在不使用接口(这将强制在所有地方重新实现树的功能)和不使用强制类型转换的情况下实现类型安全树?

我有使用树作为公共基类的想法,但是这样类型安全就没有了。我目前的方法是使用泛型。但是我缺少一些转换回基本类型。

下面是一个简化的/不工作的示例。其思想是返回的节点支持树函数,同时它们也支持它们的基本类型行为。我可以使用下面的类,而不是从Node继承,但这样一来,一方面我就失去了类型安全,而且继承也会出现问题,因为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.
}

这是一个类型安全树的实现:

public class Tree<T> : List<Tree<T>>
{
    public T Value { get; set; }
}

是的,就是这样。简单。

当然,您可以添加一两个构造函数,并将Value属性设置为只读,以使其对OOP更友好。您可以轻松地添加Parent属性。

我有使用树作为公共基类的想法,但是这样类型安全就没有了。我目前的方法是使用泛型。但是我缺少一些转换回基本类型。

然后将泛型类型约束为基类型:

public class Node<T> where T: BaseType { ... }

现在您可以创建任何类型的Node<MyDerivedType>树,只要MyDerivedType派生自BaseType

另一方面,我会考虑修改以下在你的实现:

  1. Children应该是一个属性,不要暴露字段,除非它是只读的。此外,您不应该将其公开为List;这将允许任何人直接添加或删除可能违反实现中假定的不变量的节点。返回一个IEnumerable<T>:

    private readonly List<T> children;
    public IEnumerable<T> Children => children.Select(c => c);
    

    可以直接返回children,因为它可以隐式转换为IEnumerable<T>;问题是任何人都可以简单地将其转换回List<T>并对其进行修改。

  2. Flatten也是如此(第一个f应该大写)。也考虑返回一个IEnumerable<T>

最新更新