Base class with recursive type specification C# with Example



Base class with recursive type specification C# with Example

One time definition of a generic base class with recursive type specifier. Each node has one parent and multiple 
children. 
///  
/// Generic base class for a tree structure 
///  
/// The node type of the tree 
public abstract class Tree where T : Tree 
{ 
///  
/// Constructor sets the parent node and adds this node to the parent's child nodes 
///  
/// The parent node or null if a root 
protected Tree(T parent) 
{ 
this.Parent=parent; 
this.Children=new List(); 
if(parent!=null) 
{ 
parent.Children.Add(this as T); 
} 
} 
public T Parent { get; private set; } 
public List Children { get; private set; } 
public bool IsRoot { get { return Parent==null; } } 
public bool IsLeaf { get { return Children.Count==0; } } 
///  
/// Returns the number of hops to the root object 
///  
public int Level { get { return IsRoot ? 0 : Parent.Level+1; } } 
} 
 

The above can be re-used every time a tree hierarchy of objects needs to be defined. The node object in the tree 
has to inherit from the base class with 
public class MyNode : Tree 
{ 
// stuff 
} 
each node class knows where it is in the hierarchy, what the parent object is as well as what the children objects 
are. Several built in types use a tree structure, like Control or XmlElement and the above Tree can be used as a 
base class of any type in your code. 
For example, to create a hierarchy of parts where the total weight is calculated from the weight of all the children, 
do the following: 
public class Part : Tree 
{ 
public static readonly Part Empty = new Part(null) { Weight=0 }; 
public Part(Part parent) : base(parent) { } 
public Part Add(float weight) 
{ 
return new Part(this) { Weight=weight }; 
} 
public float Weight { get; set; } 
public float TotalWeight { get { return Weight+Children.Sum((part) => part.TotalWeight); } } 
} 
to be used as 
// [Q:2.5] -- [P:4.2] -- [R:0.4] 
// \ 
// - [Z:0.8] 
var Q = Part.Empty.Add(2.5f); 
var P = Q.Add(4.2f); 
var R = P.Add(0.4f); 
var Z = Q.Add(0.9f); 
// 2.5+(4.2+0.4)+0.9 = 8.0 
float weight = Q.TotalWeight; 
Another example would in the definition of relative coordinate frames. In this case the true position of the 
coordinate frame depends on the positions of all the parent coordinate frames. 
public class RelativeCoordinate : Tree 
{ 
public static readonly RelativeCoordinate Start = new RelativeCoordinate(null, PointF.Empty) { 
}; 
public RelativeCoordinate(RelativeCoordinate parent, PointF local_position) 
: base(parent) 
{ 
this.LocalPosition=local_position; 
} 
public PointF LocalPosition { get; set; } 
public PointF GlobalPosition 
{ 
get 
{ 
if(IsRoot) return LocalPosition; 
 

var parent_pos = Parent.GlobalPosition; 
return new PointF(parent_pos.X+LocalPosition.X, parent_pos.Y+LocalPosition.Y); 
} 
} 
public float TotalDistance 
{ 
get 
{ 
float dist = 
(float)Math.Sqrt(LocalPosition.X*LocalPosition.X+LocalPosition.Y*LocalPosition.Y); 
return IsRoot ? dist : Parent.TotalDistance+dist; 
} 
} 
public RelativeCoordinate Add(PointF local_position) 
{ 
return new RelativeCoordinate(this, local_position); 
} 
public RelativeCoordinate Add(float x, float y) 
{ 
return Add(new PointF(x, y)); 
} 
} 
to be used as 
// Define the following coordinate system hierarchy 
// 
// o--> [A1] --+--> [B1] -----> [C1] 
// | 
// +--> [B2] --+--> [C2] 
// | 
// +--> [C3] 
var A1 = RelativeCoordinate.Start; 
var B1 = A1.Add(100, 20); 
var B2 = A1.Add(160, 10); 
var C1 = B1.Add(120, -40); 
var C2 = B2.Add(80, -20); 
var C3 = B2.Add(60, -30); 
double dist1 = C1.TotalDistance; 
 

Parameter(s) Description 
T, V Type placeholders for generic declarations 

0 Comment's

Comment Form