3

我正在实现一棵树,将其视为文件夹结构,因此我有一个如下所示的类:

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

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

  1. 将 AddChild(Folder) 方法添加到处理添加文件夹的文件夹,并可以设置父级。这个问题是我现在必须锁定我的 Children 集合,这样你就不能绕过这个方法。
  2. 创建我自己的 Children 集合,该集合将获得对实例的引用,因此它可以处理在添加时设置父级。这个问题我必须实现一个新的集合。
  3. 使用在添加或删除项目时具有事件的集合。

我很好奇人们通常使用什么模式,然后是否有人对我的特定用例有任何建议。我正在使用 nHibernate 将我的树持久化到 SQL 服务器。我宁愿不实现自定义集合,因为它需要很多代码才能使它适用于我的应用程序的一小部分。

4

5 回答 5

3

在查看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(); 
    }
}
于 2009-01-13T16:57:19.470 回答
1

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

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

于 2009-01-13T16:37:46.203 回答
1

我会选择选项 1,然后让 Children 属性看起来像这样:

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

现在必须调用 AddChild 来添加孩子。该集合不可访问。

于 2009-01-13T16:40:15.700 回答
1

使用数字 1,但将您的 Children 属性设置为 IEnumerable,以便用户无法添加到集合中。

于 2009-01-13T16:43:49.543 回答
1

实现自定义集合的工作量很大;对仅公开两个或三个方法的现有集合类实现包装器不是。从您对 JayArr 的回复来看,这似乎就是您要寻找的东西。就像是:

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;
      }
   }
}
于 2009-01-13T18:02:59.010 回答