The other day I (2012) discovered the power of a recursive function / method (I.e. recursion) while I was struggling to write some code. I think one of the focal points of writing good code is writing it in a way that it expands and contracts dynamically. As well, writing code that you will rarely, if ever, need to modify again.
I was writing a program that would create a Tree View containing a hierarchy of my family tree. For example:
I am sure you get the point. It can go forward and backwards (n) number of times. Initially I began writing nested foreach statements. However, it quickly became apparent that I would feasibly go on forever nesting these foreach statements like this:
[sourcecode language="csharp" padlinenumbers="true" autolinks="false" gutter="false" toolbar="false"] foreach (Parent child in Parent.Children) { if(child.children.count > 0) { foreach (Parent grandchild in child.Children) { if(child.children.count > 0) { foreach (Parent greatgrandchild in grandchild.Children) { if(child.children.count > 0) { ....FOREVER....etc... } else { list.Add(grandchild.name); } } } else { list.Add(grandchild.name); } } } else { list.Add(child.name); } } [/sourcecode]
The above approach simply would not work. In many design or code review meetings there would be a discussion about ‘How many levels do we really need’. But in the end, if you implement this approach at some point in the future you will, very likely, reach the limit. This will result in a source code modification. This is something we want to avoid.
Below is an example of how to write a recursive function / method (recursion) that will provide the functionality we failed to get in the above nested foreach approach. It will expand and contract dynamically (n) times
[sourcecode language="csharp" autolinks="false" gutter="false" toolbar="false"] public static List<TreeView> GetFamilyTree(Type ParentType) { List<TreeVIew> FamilyTree = new List<TreeVIew>(); Treeview treeview = new Treeview(ParentType); PopulateTreeview(ParentType, treeview); return FamilyTree; } [/sourcecode]
[sourcecode language="csharp" autolinks="false" gutter="false" toolbar="false"] using System.Reflection; private static void PopulateTreeview(Type ParentType, TreeviewClass node, int depth = 0) { if (depth > 1000) throw new StackOverflowException("PopulateTreeview depth > 1000"); foreach(PropertyInfo property in ParentType.GetProperties()) { string name = property.Name; TreeviewClass treeview = new TreeviewClass(name); node.Children.Add(treeview); PopulateTreeview(property.PropertyType, treeview, depth + 1); } } [/sourcecode]
The List<TreeView> is a class that I store the name and the children of a relative:
[sourcecode language="csharp" autolinks="false" gutter="false" toolbar="false"] public class TreeView { public string Name { get; private set; } public List<TreeView> Children { get; private set; } } [/sourcecode]
You can see in the PopulateTreeview method, I call the method itself, I.e. recursively. Because I am passing the treeview variable, I created in the GetFamilyTree method, the same treeview variable is updated (n) times. Awesome!!!