Skip to main content

Collect - 7 higher order functions

This is my sixth post in a series about higher order functions in C#. Here are the other ones.


The collect function is mostly used as an intelligent "flatten", as you use it to flatten out data structures. Here's the function signature.

IEnumerable<U> Collect<T, U>(Func<T, IEnumerable<U>> fn, IEnumerable<T> list)

For each item in the list, we produce a list, and in that list every item is yielded. This becomes much clearer with an example.


var numbers = new[]
    new[] { 1, 2, 3 },
    new[] { 4, 5, 6 },
    new[] { 7, 8, 9 },

var flat = numbers.Collect(arr => arr); // 1, 2, 3, 4, 5, 6, 7, 8, 9

Almost so simple it's stupid. It just flattens out the array. Let's do something closer to home. Each blog post has comments, and I would like to collect all the comments.

private class BlogPost
    public IEnumerable<Comment> Comments { get; private set; }

public static IEnumerable&lt;BlogPost&gt; All()
    // return SELECT blogpost.* FROM db


var blogPosts = BlogPost.All(); var comments = blogPosts.Collect(post => post.Comments);

When you think of it, this is also a "flatten", but with the selected property Comments. Once you understand how to use it, this higher order function is extremely useful.


The implementation of Collect is dead simple.

public static IEnumerable<U> Collect<T, U>(Func<T, IEnumerable<U>> fn, IEnumerable<T> list)
    if (list == null)
        throw new ArgumentNullException("list", "Supplied list to Collect is not allowed to be null");

if (fn == null)
    throw new ArgumentNullException(&quot;fn&quot;, &quot;Supplied function to Collect is not allowed to be null&quot;);

foreach (var item1 in list)
foreach (var item2 in fn(item1))
    yield return item2;


public static IEnumerable<U> Collect<T, U>(this IEnumerable<T> list, Func<T, IEnumerable<U>> fn) { return Collect(fn, list); }

This loops through the list, selecting the property that should be collecting, and yielding all items in those child lists. Pretty simple.


We have taken a look on collect and how to use it to flatten, not only multi leveled collections, but also object graphs. This becomes very useful in situations where the value you have is a 1..N relation with the value you really want.

comments powered by Disqus