Printed from www.rmfusion.com A Developer website designed for Developers

Iterator Pattern Code Review

Code Download

Family Tree Structure

image showing family tree structure

Define the Main Tree Object

Define the Tree class which contains the methods required to iterate through the family tree structure.

class Tree { Node m_root;
public Tree(Node head) { this.m_root = head; }
public IEnumerable<Person> Preorder { get { return this.ScanPreorder(this.m_root); } }
private IEnumerable<Person> ScanPreorder(Node root) { yield return(root.Data);
if (root.Child != null) { foreach (Person p in ScanPreorder(root.Child)) { yield return (p); } } if (root.Next != null) { foreach (Person p in ScanPreorder(root.Next)) { yield return (p); } } } public IEnumerable<Person> Where(Func<Person, Boolean> filter) { foreach (Person p in this.ScanPreorder(this.m_root)) { if (filter(p) == true) { yield return (p); } } } }

The ScanPreorder() method is the main method for transvering the tree and uses recursion to iterate from the root node to the left node and then to the right node for each node in the tree.

For the root node the method yields the data at that node, and for the left and right nodes, it yields a node to the enumerator. This node will act as the root node and the iteration will start again. In this way, the entire tree is transversed from left to right and top to bottom.

The Where() method acts as another enumerator, which also calls ScanPreorder() method but filters out the required Person objects according to the delegate supplied. The type of the delegate is Func <Person,bool>, meaning it takes a Person as a parameter on each iteration, and returns a boolean value.

The Tree class does not implement the IEnumerable<T> interface so in order to use LINQ functionality the Where() method was defined.

Define the Node and Person Objects

The Node class (object) represents the definition of a node in the tree structure.

class Node { public Node Child { get; set; } public Node Next { get; set; } public Person Data { get; set; }
public Node(Person data, Node child, Node next) { this.Data = data; this.Child = child; this.Next = next; } }

The Child property represents the first child node of the current node. The Next property represents the node to the right of the current node. The Data property represents the data stored for a particular node.

The Person class (object) represents the custom properties required for a person stored in the tree structure.

class Person { public String Name { get; set; } public Int32 Birth { get; set; }
public Person(String name, Int32 birth) { this.Name = name; this.Birth = birth; }
public override string ToString() { return (String.Format("[{0}, {1}]", this.Name, this.Birth)); } }

Use the Iterator Pattern

The Program class creates the family tree structure and stores this in a variant variable, which will at runtime be converted to a Tree type.

class Program { static void Main(string[] args) { var family = new Tree( new Node(new Person("Tom", 1950), new Node(new Person("Peter", 1976), new Node(new Person("Sarah", 2000), null, new Node(new Person("James", 2002), null, null)), new Node(new Person("Robert", 1978), null, new Node(new Person("Mark", 1982), new Node(new Person("Carrie", 2005), null, null), null))), null) );
Console.WriteLine("Full Family"); foreach (Person p in family.Preorder) { Console.Write("{0} ", p); } Console.WriteLine("\n");
var selection = from p in family where p.Birth > 1980 orderby p.Name select p;
Console.WriteLine("Born after 1980 in alpha order"); foreach (Person p in selection) { Console.Write("{0} ", p); } Console.WriteLine("\n"); Console.Read(); } }

The code transverses through the Tree structure and displays all the nodes. Finally, using LINQ syntax the family tree is filtered by birth year and results displayed.