Many objects in .NET are stored in a hierarchy. For example: controls, files and folders, and anything you would normally display in a tree view. There are many different algorithms for finding the root of a hierarchy. Here is one of them:
public MyObject GetRoot()
{
// start with this as root
MyObject root = this;
// get the parent
MyObject parent = this.Parent;
// keep going until no more parents
while (parent != null)
{
// save the parent
root = parent;
// get the parent of the parent
parent = parent.Parent;
}
return root;
}
Sample Program
Here is a simple console program that demonstrates this. Note that the function to get the root is a method GetRoot() instead of a Root property. Making it a method instead of a property implies that it must be calculated each time, similar to how the .NET Control class has a FindForm() method.
using System;
using System.Collections.Generic;
namespace CSharp411
{
class Program
{
static void Main( string[] args )
{
MyObject a = new MyObject( "a" );
MyObject b = new MyObject( "b" );
MyObject c = new MyObject( "c" );
MyObject d = new MyObject( "d" );
a.AddChild( b );
b.AddChild( c );
c.AddChild( d );
Write( a );
Write( b );
Write( c );
Write( d );
Console.ReadLine();
}
static void Write( MyObject obj )
{
string objName = obj.Name;
MyObject parent = obj.Parent;
string parentName = parent == null ? "none" : parent.Name;
MyObject root = obj.GetRoot();
string rootName = root == null ? "none" : root.Name;
Console.WriteLine( "Object={0}, Parent={1}, Root={2}", objName, parentName, rootName );
}
}
class MyObject
{
public MyObject()
{
}
public MyObject( string name )
{
this.m_Name = name;
}
private string m_Name;
public string Name
{
get
{
return this.m_Name;
}
set
{
this.m_Name = value;
}
}
public override string ToString()
{
return this.m_Name;
}
private MyObject m_Parent;
public MyObject Parent
{
get
{
return this.m_Parent;
}
}
private List<myobject> m_Children = new List</myobject><myobject>();
public void AddChild( MyObject obj )
{
this.m_Children.Add( obj );
obj.m_Parent = this;
}
public IEnumerator</myobject><myobject> Children
{
get
{
return this.m_Children.GetEnumerator();
}
}
public MyObject GetRoot()
{
// start with this as root
MyObject root = this;
// get the parent
MyObject parent = this.Parent;
// keep going until no more parents
while (parent != null)
{
// save the parent
root = parent;
// get the parent of the parent
parent = parent.Parent;
}
return root;
}
}
}
Program Output
As you would expect, the output when you run this program is:
Object=a, Parent=none, Root=a
Object=b, Parent=a, Root=a
Object=c, Parent=b, Root=a
Object=d, Parent=c, Root=a
How about:
public MyObject GetRoot()
{
if Parent == null
return this;
else
return Parent.GetRoot();
}
Hey Mikey, I like it! (classic cereal commercial reference)
Though the recursive method is 34% slower on my PC (with an average hierarchy depth of 4) it’s nice and clean.