Skip to content

Extension Method to Flatten Any Recursive Collection

May 20, 2010

Sometimes I wan’t to iterate all items in a recursive collection structure, e.g. the Controls hierarchy of Web Controls or Windows Forms Controls.

Instead of coding a “flatten” method for each collection type, I’ve written a small extension method Flatten that allows you to easily recurse any structure:

/// <summary> /// Flattens any recursive collection into a single list of all items. /// </summary> /// <typeparam name="T">Type of items in collection</typeparam> /// <param name="collection">Root collection of T items</param> /// <param name="recursor">Selector that returns the sub collection of a given item</param> /// <param name="predicate">Predicate to apply to each item before returning it</param> /// <returns>List of all items</returns> public static IList<T> Flatten<T>( this IEnumerable<T> collection, Func<T, IEnumerable<T>> recursor, Func<T, bool> predicate) { // Container for results var result = new System.Collections.Generic.List<T>(); // Queue of yet unprocessed collections var queue = new Queue<IEnumerable<T>>(); do { // Process current collection foreach (T control in collection) { queue.Enqueue(recursor(control)); if (predicate == null || predicate(control)) result.Add(control); } // Go to next or exit if done if (queue.Count > 0) collection = queue.Dequeue(); else return result; } while (true); }

The usage of it is simple:

IList<Control> allControls = Controls.Cast<Control>().Flatten(c => c.Controls.Cast<Control>(), null);

To avoid the ugly Cast<Control>() calls, you can define overloads of Flatten that works directly on ControlCollection. The reason why Cast is needed is that ControlCollection does not implement IEnumerable<Control>.


From → .NET, Uncategorized

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: