You can also write your own LINQ extension method to do this kind of thing, and use something like a stack to avoid explicit recursion (better if the nesting is very deep):
public static class LinqExtensions
{
public static IEnumerable<TP> FlattenProperties<T, TP>(this IEnumerable<T> outers,
Func<T, TP> propertySelector, Func<T, IEnumerable<T>> innersSelector)
{
Stack<T> stack = new Stack<T>(outers);
while (stack.Any())
{
T outer = stack.Pop();
TP prop = propertySelector(outer);
yield return prop;
if (innersSelector(outer) != null)
{
foreach (var inner in innersSelector(outer))
stack.Push(inner);
}
}
}
}
You can then write something like:
TaskHolder th = new TaskHolder() { ... };
var names = th.Tasks.FlattenProperties(x => x.Name, x => x.Tasks).ToList();