<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type='text/xsl' href='http://chayce-za.spaces.live.com/mmm2008-07-24_12.50/rsspretty.aspx?rssquery=en-US;http%3a%2f%2fchayce-za.spaces.live.com%2fcategory%2fSome%2bAssembly%2bRequired%2ffeed.rss' version='1.0'?><rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:msn="http://schemas.microsoft.com/msn/spaces/2005/rss" xmlns:live="http://schemas.microsoft.com/live/spaces/2006/rss" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Jonathan Chayce Dickinson: Some Assembly Required</title><description /><link>http://chayce-za.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&amp;_c=BlogPart&amp;partqs=catSome%2bAssembly%2bRequired</link><language>en-US</language><pubDate>Tue, 27 May 2008 12:26:12 GMT</pubDate><lastBuildDate>Tue, 27 May 2008 12:26:12 GMT</lastBuildDate><generator>Microsoft Spaces v1.1</generator><docs>http://www.rssboard.org/rss-specification</docs><ttl>60</ttl><cf:parentRSS>http://chayce-za.spaces.live.com/blog/feed.rss</cf:parentRSS><live:type>blogcategory</live:type><live:identity><live:id>-5288244965216934031</live:id><live:alias>chayce-za</live:alias></live:identity><cf:listinfo><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="typelabel" label="Type" /><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="tag" label="Tag" /><cf:group element="category" label="Category" /><cf:sort element="pubDate" label="Date" data-type="date" default="true" /><cf:sort element="title" label="Title" data-type="string" /><cf:sort ns="http://purl.org/rss/1.0/modules/slash/" element="comments" label="Comments" data-type="number" /></cf:listinfo><item><title>Trees and Anonymous Delegates</title><link>http://chayce-za.spaces.live.com/Blog/cns!B69C6138F2FF2771!194.entry</link><description>&lt;h1&gt;&lt;/h1&gt; &lt;h1&gt;Trees and Anonymous Delegates&lt;/h1&gt; &lt;p&gt;Something that I found to be really useful with the new .Net 2.0 anonymous delegates is &amp;quot;actioning&amp;quot;. &lt;h2&gt;Scenario&lt;/h2&gt; &lt;p&gt;I had a situation where I was recursing through a tree to perform some action against all the items. Lets set up a simple tree node:&lt;pre&gt;&lt;code&gt;    public class TreeItem : List&amp;lt;TreeItem&amp;gt;
    {
        public string Text;

        public TreeItem(string text)
        {
            Text = text;
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;The old way&lt;/h2&gt;
&lt;p&gt;Using the old naive way we could do the following:&lt;pre&gt;&lt;code&gt;    static class Program
    {
        static TreeItem RootNode = new TreeItem(&amp;quot;Root&amp;quot;);

        static void Main()
        {
            // Fill the tree with useless data.
            RootNode.Add(new TreeItem(&amp;quot;Node 1&amp;quot;));
            RootNode[0].Add(new TreeItem(&amp;quot;Node 1.1&amp;quot;));
            RootNode[0].Add(new TreeItem(&amp;quot;Node 1.2&amp;quot;));

            RootNode.Add(new TreeItem(&amp;quot;Node 2&amp;quot;));
            RootNode[1].Add(new TreeItem(&amp;quot;Node 2.1&amp;quot;));
            RootNode[1].Add(new TreeItem(&amp;quot;Node 2.2&amp;quot;));

            // Do the actions, the old way.
            TreeItem[] items = FlattenTree();
            foreach (TreeItem item in items)
                Console.WriteLine(item.Text);

            if (System.Diagnostics.Debugger.IsAttached)
                Console.ReadLine();
        }

        static TreeItem[] FlattenTree()
        {
            TreeItem newItems = new TreeItem(&amp;quot;Nothing&amp;quot;);

            FlattenTree(newItems, RootNode);

            return newItems.ToArray();
        }

        private static void FlattenTree(TreeItem newItems, 
                                        TreeItem node)
        {
            newItems.Add(node);
            foreach (TreeItem item in node)
                FlattenTree(newItems, item);
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, there are two loops occuring here (once to recurse the tree, and once to action all the items). That is far from optimal.
&lt;h2&gt;The new way&lt;/h2&gt;
&lt;p&gt;Let's see how we can optimize this further. Using anonymous delegates we can action all the items in the tree in a very clean fashion with little code changes required.&lt;pre&gt;&lt;code&gt;    static class Program
    {
        static TreeItem RootNode = new TreeItem(&amp;quot;Root&amp;quot;);

        static void Main()
        {
            // Fill the tree with useless data.
            RootNode.Add(new TreeItem(&amp;quot;Node 1&amp;quot;));
            RootNode[0].Add(new TreeItem(&amp;quot;Node 1.1&amp;quot;));
            RootNode[0].Add(new TreeItem(&amp;quot;Node 1.2&amp;quot;));

            RootNode.Add(new TreeItem(&amp;quot;Node 2&amp;quot;));
            RootNode[1].Add(new TreeItem(&amp;quot;Node 2.1&amp;quot;));
            RootNode[1].Add(new TreeItem(&amp;quot;Node 2.2&amp;quot;));

            // Do the actions, the new way.
            ActionTree(delegate(TreeItem item)
            {
                Console.WriteLine(item.Text);
            });

            if (System.Diagnostics.Debugger.IsAttached)
                Console.ReadLine();
        }

        static void ActionTree(Action&amp;lt;TreeItem&amp;gt; action)
        {
            ActionTree(action, RootNode);
        }

        private static void ActionTree(Action&amp;lt;TreeItem&amp;gt; action, 
                                       TreeItem node)
        {
            action(node);
            foreach (TreeItem item in node)
                ActionTree(action, item);
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now the tree is only being recursed, no iterating and assigning a useless array.
&lt;h1&gt;Breaking Out the Generic Solution&lt;/h1&gt;
&lt;p&gt;Now we need the ability to break out of the recursion. First we need to define a delegate.&lt;pre&gt;&lt;code&gt;    public delegate bool ContinueAction&amp;lt;T&amp;gt;(T t);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next we need to make the iteration process. Enter extension methods, after further tweaking I acheived the following:&lt;pre&gt;&lt;code&gt;    public class TreeItem : List&amp;lt;TreeItem&amp;gt;
    {
        public string Text;

        public TreeItem(string text)
        {
            Text = text;
        }
    }

    public delegate bool ContinueAction&amp;lt;T&amp;gt;(T t);

    static class Program
    {
        static TreeItem RootNode = new TreeItem(&amp;quot;Root&amp;quot;);

        static void Main()
        {
            // Fill the tree with useless data.
            RootNode.Add(new TreeItem(&amp;quot;Node 1&amp;quot;));
            RootNode[0].Add(new TreeItem(&amp;quot;Node 1.1&amp;quot;));
            RootNode[0].Add(new TreeItem(&amp;quot;Node 1.2&amp;quot;));

            RootNode.Add(new TreeItem(&amp;quot;Node 2&amp;quot;));
            RootNode[1].Add(new TreeItem(&amp;quot;Node 2.1&amp;quot;));
            RootNode[1].Add(new TreeItem(&amp;quot;Node 2.2&amp;quot;));

            // Do the actions, the generic way.
            RootNode.ActionTree&amp;lt;TreeItem&amp;gt;(delegate(TreeItem item)
            {
                if (item.Text == &amp;quot;Node 2&amp;quot;)
                    return false;
                Console.WriteLine(item.Text);
                return true;
            });

            if (System.Diagnostics.Debugger.IsAttached)
                Console.ReadLine();
        }

        private static bool ActionTree&amp;lt;T&amp;gt;(this T node, ContinueAction&amp;lt;T&amp;gt; action) where T : IEnumerable&amp;lt;T&amp;gt;
        {
            if (!action(node))
                return false;
            foreach (T item in node)
            {
                if (!ActionTree&amp;lt;T&amp;gt;(item, action))
                    return false;
            }
            return true;
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that's it! Those bound to .Net 2.0 can just remove the this from the extension method and call the method as follows:&lt;pre&gt;&lt;code&gt;    ActionTree&amp;lt;TreeItem&amp;gt;(RootNode, delegate(TreeItem item) {...});&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hope this helps!!!&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-5288244965216934031&amp;page=RSS%3a+Trees+and+Anonymous+Delegates&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=chayce-za.spaces.live.com&amp;amp;GT1=chayce-za"&gt;</description><comments>http://chayce-za.spaces.live.com/Blog/cns!B69C6138F2FF2771!194.entry#comment</comments><guid isPermaLink="true">http://chayce-za.spaces.live.com/Blog/cns!B69C6138F2FF2771!194.entry</guid><pubDate>Mon, 10 Mar 2008 14:27:29 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://chayce-za.spaces.live.com/blog/cns!B69C6138F2FF2771!194/comments/feed.rss</wfw:commentRss><wfw:comment>http://chayce-za.spaces.live.com/Blog/cns!B69C6138F2FF2771!194.entry#comment</wfw:comment><dcterms:modified>2008-03-10T14:30:09Z</dcterms:modified></item></channel></rss>