Posted in:

The nineteenth video in my exploring MoreLINQ series looks at the Generate, GenerateByIndex, Repeat, Sequence and Unfold methods.

Unlike most of the other MoreLINQ methods we've looked at so far in this series, these are designed to create new IEnumerable sequences rather than operating on existing sequences.

You can generate sequences where each element depends on the previous with Generate, or where each element depends on the index GenerateByIndex. Repeat repeats an existing sequence, while Sequence adds more capabilities to the built in LINQ Enumerable.Range method by supporting custom step values.

Finally, the Unfold method is the most powerful of them all, allowing you to maintain a state object to help you generate the next value in the sequence and decide when to stop. It allows you to do things like implement the Fibonacci sequence in a single line. The only unfortunate thing about MoreLINQ's Unfold method is that it doesn't offer simplified overloads with fewer parameters, as you don't always need the full power on offer.

So for example if we defined a helper based on the MoreLINQ Unfold method:

static IEnumerable<TResult> Unfold<TState,TResult>(TState initial, Func<TState,TState> stateSelector, Func<TState,TResult> resultSelector)
    return MoreEnumerable.Unfold(initial, s=>s, s=>true, stateSelector, resultSelector);

Then we could set up an infinite Fibonacci sequence like this:

Unfold((a:0,b:1),s => (s.b, s.a + s.b), s => s.a + s.b)

You can find all videos in this series here.

Want to learn more about LINQ? Be sure to check out my Pluralsight course LINQ Best Practices.


Comment by raboof

Thanks for another fine video in the series, Mark!
I wanted to point out that the Fibonacci sequence can also be created more simply using Generate, without going through the trouble of creating a simpler overload for Unfold:

var fib =
from s in MoreEnumerable.Generate((a: 0, b: 1), s => (s.b, s.a + s.b))
select s.a;

Your version also generates the sequence (1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …), which starts with Fib(2), whereas the Generate version above starts with Fib(0), therefore producing the more complete (0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …) sequence.

Comment by Mark Heath

Cool, that's a nice trick with Generate. I was trying to think of a good scenario to demonstrate using Unfold for, and that was the best I could come up with.

Mark Heath