For dealing with the Node not having a link to the collection, I use an abstract base class property called "HasChildren" to allow for checking, and ensure that the concrete Node implementation throws an exception if you forgot to check and tried accessing the children.
public abstract class NodeBase<T> {
public abstract bool HasChildren { get; }
public abstract ICollection<T> Children { get; set; }
}
public class NodeCollection<T> : NodeBase<T> {
public override bool HasChildren { get { return true; } }
public override ICollection<T> Children { get; set; }
}
public class Node<T> : NodeBase<T> {
public override bool HasChildren { get { return false; } }
public override ICollection<T> Children { get { throw new Exception("blah"); } set { throw new Exception("blah"); } }
}
I use an Add
method concrete implementation from an abstract base class method to work out what to add, and how, for me this also takes care of collection sorting for adding items to NodeCollections, and enforces uniqueness if required.