I'm creating a tree structure that is based on an AbstractNode class. The AbstractNode class has a generic collection property that contain its child nodes. See the code example below.
Is there some way, possibly using generics, that I can restrict a concrete version of AbstractNode to only allow one type of child node? See the code below for ConcreteNodeA, where its ChildNodes property is a collection of ConcreteNodeB rather then AbstractNode. This of course does not compile, but I'm wondering if there is some other method I could use to have the same effect.
Of course everything will work with the the ChildNodes collection property always being of type AbstractNode, but I'm trying to embed some logic into my classes in regards to what nodes should be the children of other nodes. Plus when referencing the ChildNodes property it would be nice if I didn't have to cast the collection into a collection of the type I know it should be.
public abstract class AbstractNode
{
public abstract NodeCollection<AbstractNode> ChildNodes
{
get;
set;
}
}
public class ConcreteNodeA : AbstractNode
{
//THIS DOES NOT COMPLILE
//Error 1 'ConcreteNodeA.ChildNodes': type must be 'NodeCollection<AbstractNode>'
//to match overridden member 'AbstractNode.ChildNodes'
public override NodeCollection<ConcreteNodeB> ChildNodes
{
get;
set;
}
}
public class ConcreteNodeB : AbstractNode
{
public override NodeCollection<AbstractNode> ChildNodes
{
get;
set;
}
}
public class NodeCollection<T> : BindingList<T>
{
//add extra events here that notify what nodes were added, removed, or changed
}
Update
Alright I think I figured out what I want to do but I'd like to know if anyone thinks this "feels bad" or "smells funny" and why. Rather then my nodes having a ChildNodes collection property I'm thinking of making each Node the actual collection. So my tree structure is would really just be a series of collections of collections. My abstract Node classes will then use various constraints on the generic to control the kinds of sub nodes it can have.
Does this make sense? Is there a reason I wouldn't want to do this? I've never used generics in one of my own classes before so I'm not sure if I'm overlooking something.
public interface INode
{
}
public abstract class AbsNode<T> : BindingList<T>, INode where T : INode
{
}
public abstract class AbsNodeA<T> : AbsNode<T> where T : AbsSubNodeA
{
}
public abstract class ConcreteNodeA : AbsNodeA<AbsSubNodeA>
{
}
public abstract class AbsSubNodeA : INode
{
}
public class ConcreteSubNodeA :AbsSubNodeA
{
}
public class ConcreteSubNodeB :AbsSubNodeA
{
}