I wake up this morning to find a comment from Stefan regarding my post yesterday about flattening recursion:

In the future version of C# we may receive a new language construct yield foreach which will eliminate this problem. Read this paper by Erik Meijer or this blog post by Wes Dyer if you are interested.

Ironically, I had read the paper and associated blog post last week.

And it got me thinking: could I abstract out my recursive traversal?

Even better: could I abstract it out in a way that was Linq-friendly?

The answer to both: oh yeah.

Check out the browser-friendly source here.

Now the code to find all of the selected directories becomes

SubDirectories
.SelectRecursive(directory => directory.SubDirectories)
.Where(directory => directory.IsSelected);

How's that for straight-forward?

Note 1: The savvy reader will notice that the third implementation is now like the original: the target node is not included in SelectedDirectories if it is selected. I like this more.

Note 2: Since I made SelectRecursive more general, I'm not quite as efficient about creating a bunch of enumerable instances. I still (likely) save a lot in call stack space and having a general implementation is pretty cool.

Note 3: You'll notice that SelectRecursive handles the case where there recursiveSelector returns null. This is different than how default extensions like SelectMany work. It made my usage in this scenario cleaner, but it's important to note. Or not. This bothered me for reasons I'll go into in another post. The code as checked-in now throws if null is returned. These subtle implementation details can cause headaches later.

As I mentioned yesterday, you can get the full source code from my SVN repository. The new methods extension methods have been added to Extensions.cs in J832.Common.

Happy recursive Linq-ing!