2009-01-13 47 views
3

我实现一棵树把它看作一个文件夹结构,所以我有一个类,看起来像:实现在C#中的树管理父子

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

现在我想要的是能走路在树的上下,给定一个根,我可以找到一片叶子,并给出一片叶子,我可以找到根节点。所以每个孩子都需要一位家长。现在问题是向树添加新节点的最佳方式是什么。我过去使用过两种解决方案:

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

我很好奇人们通常使用什么样的模式,然后如果有人对我的具体用例有什么建议。我使用nHibernate将我的树保存到SQL服务器。我宁愿不实施自定义集合,因为它是很多代码才能使它适用于我的应用程序的一小部分。

+0

我在寻找既NHibernate和更普遍的想法...有一个很好的职位有收集某人删除... – JoshBerke 2009-01-13 18:44:12

回答

3

寻找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(); 
    } 
} 
1

就个人而言,我会采用方法1.允许客户端代码操纵Children集合直接违反封装,因此'锁定'Children集合是正确的事情™。

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

+0

那么你将如何防止他们修改集合?你使用什么策略? ReadOnlyCollection?返回集合的副本? – JoshBerke 2009-01-13 16:40:04

+0

@Josh: 一种方法返回一个IEnumerable: 公共IEnumerable的儿童 { 得到 { 的foreach(文件夹的孩子在儿童) { 产量回报的孩子; } } } – SchaeferFFM 2009-01-14 14:41:40

1

我会去的选项1,然后让儿童属性是这样的:

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

现在的AddChild必须调用添加的儿童。该集合不可访问。

+0

只要客户端不想索引进入IList <> ...如果你的孩子是一本字典,就会很好地工作... – JoshBerke 2009-01-13 16:46:55

1

与编号1一起使用,但使您的Children属性IEnumerable,以便用户不能添加到集合。

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; 
     } 
    } 
}