C# 每个级别具有不同类型的泛型非二叉树

C# 每个级别具有不同类型的泛型非二叉树,c#,data-structures,tree,polymorphism,C#,Data Structures,Tree,Polymorphism,我正在尝试创建一个通用的对象层次结构树,它允许按名称和id进行对象查找以及遍历。基类如下所示: public abstract class RuntimeObject { public Guid Id {get;} public string Name {get;} public Type ObjectType {get;} protected RuntimeObject( string name ) { Id = Guid.NewGuid(); Name

我正在尝试创建一个通用的对象层次结构树,它允许按名称和id进行对象查找以及遍历。基类如下所示:

public abstract class RuntimeObject
{
  public Guid Id {get;}
  public string Name {get;}
  public Type ObjectType {get;}

  protected RuntimeObject( string name )
  {
    Id = Guid.NewGuid();
    Name = name;
  }
}
此类将由作为层次结构一部分的类继承

接下来,我想对此进行扩展,以添加对在父级和子级之间导航的支持,同时保持通用性,不要求顶级父级定义父字段,也不要求叶对象定义子字段。尝试这样做会变得非常混乱,我的设计方法非常糟糕:

// Top-level parent class
public abstract class RuntimeObject<TChild> : RuntimeObject
  where TChild : RuntimeObject<RuntimeObject<TChild>>
{
  public int ChildCount {get;}
  public TChild FirstChild {get;}
}

// Middle-level class
public abstract class RuntimeObject<TParent,TChild> : RuntimeObject
  where TParent : RuntimeObject<RuntimeObject<TParent,TChild>>
  where TChild : RuntimeObject<RuntimeObjecT<TParent,TChild>>
{
  public TParent Parent {get;}
  public RuntimeObject<TParent,TChild> NextSibling {get;}

  public int ChildCount {get;}
  public TChild FirstChild {get;}
}

// Leaf class
public abstract class RuntimeObject<TParent> : RuntimeObject
  where TParent : RuntimeObject<RuntimeObject<TParent>>
{
  public TParent Parent {get;}
  public RuntimeObject<TParent> NextSibling {get;}
}
这种实现不起作用,但其思想是:我想创建一个通用系统来实现对象的可遍历层次结构,并希望避免在不需要时需要具体类来定义父字段或子字段


是否有一种设计模式可以实现这一点?有人对如何构造它有什么建议吗?

如果使用一个类来表示有子节点或没有子节点的节点,则可以通过查看节点是否有子节点来判断节点是否为叶节点。阅读属性。如果子元素为null或空,这取决于您如何编写它,那么它就是一片叶子。那很容易

如果定义单独的类来表示叶节点,则节点现在有两种方式成为叶节点。它可以是叶节点类型,也可以是没有子节点的分支节点。这有点尴尬,除非节点是不可变的,或者不能使用null子节点构造,并且子节点不能设置为null,否则这意味着您必须始终执行这两个检查。它是叶节点吗?首先检查它的类型。如果它不是叶节点类型,也检查它是否有子节点。在遍历它时,您也必须这样做。首先确保它不是叶子类型,并查看它是否有子对象

如果树节点是不可变的,这将使构建树变得混乱。在不知道节点是否有子节点的情况下,无法构造节点,如果节点确实有子节点,则必须提供它们。这些孩子也是如此。这可能有一个场景,但是你的节点不是一成不变的,所以我猜这不是你想要的。即使在这种情况下,定义一个单独的类仍然会使遍历树变得更加困难

这也意味着定义新类型,这些新类型只表示处于不同状态的现有类型。换句话说,没有子节点的节点已经由正常的分支节点类表示。检查节点并查看是否有子节点很容易。事实上,对于叶节点类型,您必须同时检查类型和属性,并且这两个检查基本上会告诉您相同的事情,这说明了为什么该类型是冗余的。从字面上看,这只是表示同一事物的另一种方式

定义单独的类型意味着新类型的存在只是为了描述处于特定状态的现有类型。在大多数情况下,我们希望通过调用对象的方法或检查对象的属性来与对象交互,而不是通过检查对象的类型。但那是你必须做的。您必须始终检查每个节点的类型。如果它与检查财产的目的完全相同,我们就不必这样做

public class A : RuntimeObject<B>
{ ... }

public class B : RuntimeObject<A,C>
{ ... }

public class C : RuntimeObject<B>
{ ... }