代码之家  ›  专栏  ›  技术社区  ›  JoshBerke

在C管理父子关系中实现树

  •  3
  • JoshBerke  · 技术社区  · 16 年前

    我正在实现一个树,将其视为一个文件夹结构,因此我有一个类,它看起来像:

    public class Folder
    {
        //Various Props like Name etc.
        public IList<Folder> Children{get;}
        public Folder Parent {get;}
    }
    

    现在我想要的是能够在树上来回走动,这样给了根我就能找到一片叶子,给了叶我就能找到根节点。所以每个孩子都需要父母。现在的问题是,向树中添加新节点的最佳方法是什么。我过去使用过两种解决方案:

    1. 将AddChild(文件夹)方法添加到处理添加文件夹的文件夹,并可以设置父级。问题是我现在必须锁定我的children集合,这样您就不能绕过此方法。
    2. 创建我自己的子集合,该集合将被返回到实例的引用,以便它可以在添加时处理设置父集合。这个问题我必须实现一个新的集合。
    3. 使用在添加或删除项时包含事件的集合。

    我很好奇人们通常使用什么模式,然后如果有人对我的特定用例有任何建议。我正在使用nhibernate将树持久化到SQL Server。我不想实现自定义集合,因为要使它适用于我的应用程序中非常小的部分,需要很多代码。

    5 回复  |  直到 16 年前
        1
  •  3
  •   Jack Ryan    16 年前

    看完之后 on MSDN 你可以试试这个:

    List<Folder> children;
    
    public ReadOnlyCollection<Folder> Children
    {
        get { return this.children.AsReadOnly(); }
    }
    

    如果您的私人成员必须声明为IList,那么我们可以将其复制到列表中,然后返回它。但我真的不认为将具体的实现作为私有成员使用会有什么问题。稍后更改实现不会破坏兼容性。

    IList<Folder> children;
    
    public ReadOnlyCollection<Folder> Children
    {
        get 
        { 
            return new List<Folder>(this.children).AsReadOnly(); 
        }
    }
    
        2
  •  1
  •   Rob Prouse    16 年前

    使用数字1,但使您的子属性为IEnumerable,这样用户就不能添加到集合中。

        3
  •  1
  •   Harper Shelby damiankolasa    16 年前

    就我个人而言,我会采用方法1。在任何情况下,允许客户端代码操作子集合都会直接违反封装,因此“锁定”子集合是正确的。

    保持节点关系正确的“正确”策略取决于客户机的需求。我假设在这种特定的情况下,您希望客户机能够更改子节点本身,而不是子集合。如果是这样的话,我认为Rob Prouse的建议(使Children属性返回IEnumerable)可能是最佳选择。在其他情况下,readonlycollection可能更好。

        4
  •  1
  •   Robert Rossney    16 年前

    实现一个自定义集合需要很多工作;实现一个只公开两个或三个方法的现有集合类的包装器不是这样的。从您对Jayar的响应来看,这似乎就是您要寻找的。类似:

    public class ChildCollection
    {
       // _Children is maintained by the Folder class, hence the internal access specifier
       internal Dictionary<KeyType, Folder> _Children = new Dictionary<KeyType, Folder>;
    
       public this[KeyType key]
       {
          get
          {
              return _Children[key];
          }
       }
    
       public IEnumerable<KeyType> Keys
       {
          get
          {
             return _Children.Keys;
          }
       }
    }
    
        5
  •  1
  •   bdukes Jon Skeet    16 年前

    我将使用选项1,然后使Children属性如下所示:

        public IEnumerable<Folder> Children
        {
            get { return this.children.GetEnumerator(); }
        }
    

    现在必须调用AddChild才能添加子级。集合不可访问。