【问题标题】:How to Create a Class That Can Have Parent and Child Relationship如何创建一个可以有父子关系的类
【发布时间】:2011-02-23 16:23:17
【问题描述】:

我在这里看到了很多关于我的问题的文章,但没有一个真正回答我的问题。我正在创建一个 Branch 对象类,您可以将其设想为就像 TreeView 控件的 TreeNode 对象一样。每个分支可以在其下方(因此在上方)有任意数量的分支子级。这是我相当简单的课程:

public class Branch {
    public string Name { get; set; }
    public string Link { get; set; }
    public Branch Parent { get; private set; }
    public List<Branch> Children { get; set; }

    internal Branch(string Name, string Link) {
        this.Name = Name;
        this.Link = Link;
        this.Children = new List<Branch>();
    } // Branch - Constructor - Overload

    internal Branch(string Name, string Link, List<Branch> Children) {
        this.Name = Name;
        this.Link = Link;
        this.Children = Children;

        this.Children.ForEach(delegate(Branch branch) {
            branch.Parent = this;
        });
    } // Branch - Constructor - Overload

    public bool HasChildren {
        get { return this.Children.Count > 0; }
    } // HasChildren - Property - ReadOnly

    public string Path {
        get {
            string Result = "";

            Branch parent = this;
            while (parent != null) {
                Result = string.Format("{0}/{1}", parent.Name, Result);
                parent = parent.Parent;
            } // while stepping up the tree

            return string.IsNullOrWhiteSpace(Result) ? "" : Result.Substring(0, Result.Length - 1);
        } // get
    } // Path - Property - ReadOnly

如果我像下面这样在实例化时添加子项,这将非常有用:

List<Branch> Branches = new List<Branch>() {
    new Branch("First", "#"),
    new Branch("Second", "#"),
    new Branch("Third", "#", new List<Branch>() {
        new Branch("ThirdSub1", "#"),
        new Branch("ThirdSub2", "#")
    }),
    new Branch("Fourth", "#"),
    new Branch("Fifth", "#"),
    new Branch("Sixth", "#", new List<Branch>() {
        new Branch("SixthSub1", "#"),
        new Branch("SixthSub2", "#", new List<Branch>() {
            new Branch("SixthSub2Sub1", "#"),
            new Branch("SixthSub2Sub2", "#"),
            new Branch("SixthSub2Sub3", "#", new List<Branch>() {
                new Branch("Deep Deep Deep Undercover", "#"),
            }),
        }),
    }),
    new Branch("Seventh", "#"),
    new Branch("Eighth", "#"),
};

但如果我执行以下操作:

List<Branch> Branches = new List<Branch>();
Branch Test = Branches.Add(new Branch("Something", ""));
Test.Children.Add(new Branch("Child Here", ""));

“Child Here”节点没有与之关联的 Parent。因此它被破坏了,当然 Path 属性不起作用。

我以为我可以覆盖 List 的 Add 方法,但这是不允许的。处理这个问题的最佳方法是什么?目前我没有创建我自己的 Collection 类,比如我喜欢的 MyBranches,但是如果有一种方法可以在实现 IList 或 ISet 或 Collection 时做我需要的事情,那么我愿意这样做。但请举个例子。

谢谢!

【问题讨论】:

  • 为您的分支类型尝试扩展方法。这是一种添加重载的方法。也就是说,如果您的类型继承自 IList。不幸的是,您将无法访问受保护或私人成员。

标签: c# generics collections hierarchy


【解决方案1】:

仅针对未来寻求相同解决方案的人,这是完整的课程:

public class Branch {
    public string Name { get; set; }
    public string Link { get; set; }
    public Branch Parent { get; set; }
    public TreeBranches Children { get; private set; }

    internal Branch(string Name, string Link) {
        this.Name = Name;
        this.Link = Link;
        this.Children = new TreeBranches(this);
    } // Branch - Constructor - Overload

    internal Branch(string Name, string Link, TreeBranches Children) {
        this.Name = Name;
        this.Link = Link;
        this.Children = Children;

        this.Children.ToList().ForEach(delegate(Branch branch) {
            branch.Parent = this;
        });
    } // Branch - Constructor - Overload

    /// <summary>
    /// Returns a boolean indicating if the given Branch has any child Branches.
    /// </summary>
    public bool HasChildren {
        get { return this.Children.Count > 0; }
    } // HasChildren - Property - ReadOnly

    /// <summary>
    /// Gets the path from the oldest ancestor to the current Branch.
    /// </summary>
    public string Path {
        get {
            string Result = "";

            Branch parent = this;
            while (parent != null) {
                Result = string.Format("{0}/{1}", parent.Name, Result);
                parent = parent.Parent;
            } // while stepping up the tree

            return string.IsNullOrWhiteSpace(Result) ? "" : Result.Substring(0, Result.Length - 1);
        } // get
    } // Path - Property - ReadOnly

} // Branch - Class

public class TreeBranches : IList<Branch> {
    private List<Branch> branches = new List<Branch>();
    private Branch owner;

    public TreeBranches() {
        this.owner = null;
    }

    public TreeBranches(Branch owner) {
        this.owner = owner;
    }

    public void Add(Branch branch) {
        branch.Parent = this.owner;
        this.branches.Add(branch);
    }

    #region Standard IList Method Implementation

    IEnumerator<Branch> IEnumerable<Branch>.GetEnumerator() { return this.branches.GetEnumerator(); }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.branches.GetEnumerator(); }
    public int IndexOf(Branch item) { return this.branches.IndexOf(item); }
    public void Insert(int index, Branch item) { this.branches.Insert(index, item); }
    public void RemoveAt(int index) { this.branches.RemoveAt(index); }
    public Branch this[int index] {
        get { return this.branches[index]; }
        set { this.branches[index] = value; }
    }

    public void Clear() { this.branches.Clear(); }
    public bool Contains(Branch item) { return this.branches.Contains(item); }
    public void CopyTo(Branch[] array, int arrayIndex) { this.branches.CopyTo(array, arrayIndex); }
    public int Count { get { return this.branches.Count(); } }
    public bool IsReadOnly { get { return this.IsReadOnly; } }
    public bool Remove(Branch item) { return this.branches.Remove(item); }

    #endregion Standard IList Method Implementation
} // TreeBranches - Class

【讨论】:

  • 这已经解决了。谢谢里德!
  • 尽管如此,这并不能真正回答问题。这只有 1 级深。如果我将 Child (Branch) 添加到 Child Branch 对象之一,则其 Parent 未设置,因为此时它正在使用无法覆盖的内部 List 的 Add 方法。
  • @Grandizer:它应该 - 而不是使用列表,而是在分支内部使用 MyBranches。这样,添加元素总是设置父元素,无论它发生在什么级别......
  • @Grandizer:只要确保在 Branch 类中将其定义为 MyBranches Children,而不是 List&lt;Branch&gt; Children。 (它也不需要公共设置器 - 它应该在构造函数中创建,“this”作为所有者,私有设置器)
  • @Reed-Copsey - 是的,我看了一会儿后发现了它。再次感谢您的所有帮助。
【解决方案2】:

您可以从Collection&lt;T&gt; 派生而不是List&lt;T&gt;List&lt;T&gt; 更快,并且针对性能进行了优化,但Collection&lt;T&gt; 更具可扩展性并且允许您覆盖Add() 和其他。

如果性能不是问题,则使用 Collection&lt;T&gt;,如果性能是问题,则使用 Reed 的示例,即在您自己的类中包含 List&lt;T&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-12
    • 1970-01-01
    • 2015-05-17
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    相关资源
    最近更新 更多