C # 2.0 Generic tree containing multiple types

I'm having a tough time figuring out how best to approach this particular issue, and I would really love the guidance from the expert community!

Let's say I have 3 classes

Branch
Twig
Leaf

      

A Branch

can contain a collection of other objects Branch

, but it can also contain a collection of objects Twig

and a collection of objects Leaf

.

A Twig

can contain a collection of other objects Twig

, but it can also contain a collection of objects Leaf

.

Object A Leaf

can be considered an underlying component and does not contain collections of any other objects.

Therefore, possible structures

Branch

Branch                Branch                  Branch
|                     |                       |
|_Branch              |_Twig                  |_Leaf
|  |_etc...           |  |_etc...
|                     |
|_Twig                |_Leaf
|  |_etc...
|
|_Leaf

      

Twig

Twig                  Twig
|                     |
|_Twig                |_Leaf
|  |_etc...
|
|_Leaf

      

sheet

Leaf

      

Given Branch

, I would like to be able to interrogate any descendant objects Branch

, Twig

or Leaf

and know

  • The relationship that each offspring object contributes to the top object (the relationship is contextual for the parent and child in each case).

  • Where child objects of a specific type contain a specific property value. For example check descendent objects Leaf

    to see if there are more than 4 property valuesUnderSide

    "Furry"

I would also like to be able to

3.enumerate through descendant level objects simultaneously, i.e. an ordered list of all first children followed by all minor children, etc. (the order of the objects at each level doesn't matter).

  1. enumerate objects by width, i.e. an ordered list of the first child, and if the first child has children then the first child children, then if this object has children, then these are children .... then the second child, etc.

My first thought is to use common tree and interface polymorphism, but I am having a hard time figuring out the details - Twig

and Leaf

objects have common properties, but objects are Branch

very different. If I were only dealing with one type of object, it would be very easy! Is it safe to do this?

Any help would be greatly appreciated.

+2


source to share


3 answers


I would use interfaces to dictate who can hold what:

public interface IBranch { }
public interface ITwig { }

public class Branch : IBranch
{
    List<IBranch> _Kids = new List<IBranch>();
    public List<IBranch> Kids
    {
        get { return _Kids; }
    }
}

public class Twig : ITwig, IBranch
{
    List<ITwig> _Kids;
    public List<ITwig> Kids
    {
        get { return _Kids; }
    }
}

public class Leaf : ITwig, IBranch
{
}

      



implement ienumerable and make sure you "return this" before listing the children. it would be nice to put all the common functionality in IBranch and the generality between leaf and twig in ITwig.

hope this helps!

+3


source


They all share the Ratio property, although they don't, so you could at least implement them with some sort of IRatio interface ...



+1


source


This is how I will probably do it:

public interface INodeChild
{
    public INodeParent Parent {get;set;}
    //Any methods/properties common to ALL inheritors
}

public abstract class NodeParent : INodeChild
{
    public INodeParent Parent {get; protected set;}

    public IList<INodeChild> Children {get;set;}
    // This is just breadth-wise since I'm more familiar with that.
    public string ListChildren(int level)
    {
        StringBuilder sb = new StringBuilder();
        foreach(INodeChild item in Children)
        {
            sb.AppendLine(Enumerable.Repeat(" ", level));
            INodeParent itemParent = item as INodeParent;
            if(itemParent != null)
            {
                itemParent.ListChildren(++level);
            }
        }
        return sb.ToString();
    }
    //Any methods/properties common to all parent inheritors (brach/twig/etc)
}

public class Brach : NodeParent
{
    // Any branch only stuff goes here.
}

public class Twig : NodeParent
{
    // Any twig only stuff goes here
}

public class Leaf : INodeChild
{
    // Any leaf only stuff goes here.
}

      

+1


source







All Articles