如何限制树结构中节点的子节点

Eri*_*tas 5 c# generics tree data-structures

我正在创建一个基于AbstractNode类的树结构。该是AbstractNode类具有包含其子节点的通用集合属性。请参阅下面的代码示例。

有没有办法,可能使用泛型,我可以限制AbstractNode的具体版本只允许一种类型的子节点?请参阅下面的ConcreteNodeA代码,其中的 ChildNodes 属性是ConcreteNodeB而不是AbstractNode的集合。这当然不能编译,但我想知道是否有其他方法可以用来达到同样的效果。

当然,一切都将与ChildNodes集合属性一起工作,该属性始终为AbstractNode类型,但我试图将一些逻辑嵌入到我的类中,以了解哪些节点应该是其他节点的子节点。另外,在引用ChildNodes属性时,如果我不必将集合转换为我知道它应该是的类型的集合,那就太好了。

public abstract class AbstractNode
{

    public abstract NodeCollection<AbstractNode> ChildNodes
    {
        get;
        set;
    }
}

public class ConcreteNodeA : AbstractNode
{
    //THIS DOES NOT COMPLILE
    //Error 1   'ConcreteNodeA.ChildNodes': type must be 'NodeCollection<AbstractNode>' 
    //to match overridden member 'AbstractNode.ChildNodes'  
    public override NodeCollection<ConcreteNodeB> ChildNodes
    {
        get;
        set;
    }
}

public class ConcreteNodeB : AbstractNode
{
    public override NodeCollection<AbstractNode> ChildNodes
    {
        get;
        set;
    }
}

public class NodeCollection<T> : BindingList<T>
{ 
    //add extra events here that notify what nodes were added, removed, or changed
}
Run Code Online (Sandbox Code Playgroud)

更新

好吧,我想我知道我想做什么,但我想知道是否有人认为这“感觉不好”或“闻起来很有趣”以及为什么。而不是我的节点具有 ChildNodes 集合属性,我正在考虑使每个节点成为实际的集合。所以我的树结构实际上只是一系列集合。然后,我的抽象 Node 类将对泛型使用各种约束来控制它可以拥有的子节点的种类。

这有意义吗?有什么理由我不想这样做吗?我以前从未在我自己的一个类中使用过泛型,所以我不确定我是否忽略了一些东西。

public interface INode
{

}

public abstract class AbsNode<T> : BindingList<T>, INode where T : INode
{

}

public abstract class AbsNodeA<T> : AbsNode<T> where T : AbsSubNodeA
{

}

public abstract class ConcreteNodeA : AbsNodeA<AbsSubNodeA>
{

}

public abstract class AbsSubNodeA : INode
{

}

public class ConcreteSubNodeA :AbsSubNodeA
{

}

public class ConcreteSubNodeB :AbsSubNodeA
{

}
Run Code Online (Sandbox Code Playgroud)

mik*_*ike 0

可以像

public abstract class AbstractNode<T> //where T : AbstractNode
{

  public abstract NodeCollection<T> ChildNodes
  {
    get;
    set;
  }
}
Run Code Online (Sandbox Code Playgroud)

可能工作吗?只是不确定注释掉的部分

编辑:这在里面感觉真的很糟糕,但它编译了......

  public abstract class BaseNode
  {
  }

  public abstract class AbstractNode<T> : BaseNode where T : BaseNode
  {
    public abstract NodeCollection<T> ChildNodes
    {
      get;
      set;
    }
  }

  public class ConcreteNodeA : AbstractNode<ConcreteNodeA>
  {
    public void Special() { }

    public override NodeCollection<ConcreteNodeA> ChildNodes
    {
      get;
      set;
    }
  }

  public class ConcreteNodeB : AbstractNode<ConcreteNodeA>
  {
    public void DoSomething()
    {
      ChildNodes[0].ChildNodes[0].ChildNodes[0].Special();
    }

    public override NodeCollection<ConcreteNodeA> ChildNodes
    {
      get;
      set;
    }
  }

  public class NodeCollection<T> : BindingList<T>
  {
    //add extra events here that notify what nodes were added, removed, or changed
  }
Run Code Online (Sandbox Code Playgroud)