Asynchronous enumerations - Part 3: IObservable

For background, read the introduction.

In part 2 I briefly mentioned that if you have simple filtering needs then you might implement your own LINQ-like methods. Well if you have more advanced filtering needs there is already something out there to help you; Reactive Extensions (Rx). The only thing you have to do is to expose your data result as an IObservable<T>. So are there no disadvantages with this approach? Well I think there are several.

  • Rx have a very long set of extension methods to do all kind of fancy things to your data collection. Except for really simple stuff the learning curve can be quite steep since there often are many ways to achieve the same thing.
  • Some interfaces have unexpected results at first glance. For example the Count() function does not return an integer but an IObservable<int>. Naturally that is the way it has to be in order to be asynchronous, but for new developers this adds to the learning curve of Rx and easily leads into misunderstandings.
  • A lot of developers are very familiar with IEnumerable and LINQ. Tasks and async/await are becoming household knowledge for more developers each day. Rx is a new framework you have to learn.
  • Since Rx uses IObservables rather than IEnumerables and Tasks your code will be inconsistent in its use of asynchronous patterns. Something that might have impact on your maintainability.
  • Rx is a framework that is not part of .Net but must be downloaded separately (even though it is developed by Microsoft).

As you can see; while Rx is a great fit for asynchronous enumerations (because it is what it really is), it uses clever constructs rather than language support to achieve this. Things that are clever often end up complex rather than simple and complex stuff typically breaks. But if your project already uses Rx a lot then it's a no-brainer; use Rx!