LINQ Query Syntax and Type Argument Inference

In LINQ, you can query in-memory data collections using Method Syntax (the IEnumerable extension methods) or Query Syntax (the SQL-like, declarative syntactic sugar on top of the underlying method calls).  I was using the query syntax to join a few in-memory collections and then project (like a SQL SELECT) the denormalized data into a new object that only contained a few pieces of information from each of the separate data collections.  The code could look similar to this (we’ll go with a shopping example in honor of the upcoming holiday season):

var shoppingLists =
    from person in people
    join wishlist in wishlists on person.Id equals wishlist.personId
    join store in stores on store.Id equals wishlist.storeId
    select new
    {
        PersonName = person.Name,
        StoreName = store.Name,
        NumItems = wishlist.Items.Count
    };

However, I ran into the following intellisense red squiggly error in the Visual Studio C# code editor on the second join statement:

The type arguments for method ‘IEnumerable<TResult> System.Linq.Enumerable.Join<TOuter,TInner,TKey,TResult>(this IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter,TKey>, Func<TInner,TKey>, Func<TOuter,TInner,TResult>)’ cannot be inferred from the query.

The error might also end with a statement that says "Try specifiying the type arguments explicitly."

Let’s Take a Closer Look…

The underlying problem is best understood by examining the method signature of the LINQ Join extension method and how the LINQ query syntax for the keyword join maps to that method call in the compiler.  The type signature for the extension method is as follows:

public static IEnumerable<TResult> Join<TOuter,TInner,TKey,TResult>(
    this IEnumerable<TOuter> outer,
    IEnumerable<TInner> inner,
    Func<TOuter,TKey> outerKeySelector,
    Func<TInner,TKey> innerKeySelector,
    Func<TOuter,TInner,TResult> resultSelector)

Consistent with all extension methods, it is public static and has a this keyword in front of the first method parameter, allowing you to call the Join method as if it had been declared in the original definition of the IEnumerable<> class or one of its inheriting children classes.

The first two parameters are the two data collections being joined, and in the case of my LINQ query above, they would be the joined collection of people & wishlists and then the stores collection, respectively.

The next two method parameters take delegates or lambda expressions that select the key value from each collection participating in the join, outer collection key selector first and then the inner key selector second.  The key values of each item in each collection will compared to each other for equality.  It will use the normal definition of the Equals method for your object type (or if you specified a custom one in your class definition), or there is another Join extension method signature that takes in another method parameter that an object that conforms to the IEqualityComparer<TKey> interface.  The key selectors from our LINQ query sample would be the two member access expressions in the "on store.Id equals wishlist.storeId" statement.

The last parameter is a delegate or lambda expression that takes in a item from each participating data collection and projects the items into a new form (like the Select LINQ query method and its SQL equivalent).  The two items being passed into the Func have passed the equality comparison of each item’s key value, exactly the same as how rows from two tables match up in an inner join statement in SQL.

As for the generic type parameters in this extension method definition, TOuter and TInner are the types from the two collections participating in the join.  TKey is the type returned by the key selectors; notice that in order to compare the equality of each key selected, they need to be of the same type.  In our example, TKey is likely int or long (or maybe Guid) since we’re dealing with Id properties of all of our objects.  TResult is the type returned by the projection Func<TOuter,TInner,TResult> resultSelector; in our case, we returned an anonymous type consisting of three properties (PersonName, StoreName, and NumItems).

Ok, So Where Did I Screw Up Then?

To answer this, let’s take a look one more time at my LINQ query syntax, how it would map to LINQ method syntax, and the Join method signature again all side-by-side:

var shoppingLists =
    from person in people
    join wishlist in wishlists on person.Id equals wishlist.personId
    join store in stores on store.Id equals wishlist.storeId
    select new
    {
        PersonName = person.Name,
        StoreName = store.Name,
        NumItems = wishlist.Items.Count
    };

// Equivalent LINQ method syntax
var shoppingLists2 = people
    .Join(wishlists,
        person => person.Id,
        wishlist => wishlist.personId,
        (person, wishlist) => new { person, wishlist })
    .Join(stores,
        store => store.Id,
        something => something.wishlist.storeId,
        (obj, store) => new
        {
            PersonName = obj.person.Name,
            StoreName = store.Name,
            NumItems = obj.wishlist.Items.Count
        });

public static IEnumerable<TResult> Join<TOuter,TInner,TKey,TResult>(
    this IEnumerable<TOuter> outer,
    IEnumerable<TInner> inner,
    Func<TOuter,TKey> outerKeySelector,
    Func<TInner,TKey> innerKeySelector,
    Func<TOuter,TInner,TResult> resultSelector)

The issue is lines 19 and 20 above; they need to be switched.  The compiler can’t properly infer the generic type parameters because we have our key selectors out of order in the argument list when invoking the Join method.  If you wanted to be explicit about your generic type parameters assignments, then Join<TOuter, TInner, TKey, TResult> would be Join<Temp1, Store, int, Temp2>, where Temp1 and Temp2 represent the magical type definitions that the compiler creates underneath the covers when you use anonymous types in your C# code.  Notice the outerKeySelector needs to come before the innerKeySelector.  It appears the "on store.Id equals wishlist.storeId" syntax is not a commutative operation.

One last thing, I just realized that the error(s) given in Visual Studio when you actually compile the code are different than the intellisense red squiggly error message.  It appears an actual build of the code is able to be a little more omniscient than the quick compile that intellisense does as you type.  The error (and intelligent suggestion) the compiler offers says something like this:

The name ‘store’ is not in scope on the left side of ‘equals’.  Consider swapping the expressions on either side of ‘equals’.

Additional Info

While reading the MSDN article on the LINQ Join method, I thought the "Remarks" section has some really great stuff about deferred execution, default equality comparison, differences from SelectMany, sort order perseverance, and so on:

This method is implemented by using deferred execution. The immediate return value is an object that stores all the information that is required to perform the action. The query represented by this method is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach in Visual C# or For Each in Visual Basic.

The default equality comparer, Default, is used to hash and compare keys.

A join refers to the operation of correlating the elements of two sources of information based on a common key. Join brings the two information sources and the keys by which they are matched together in one method call. This differs from the use of SelectMany, which requires more than one method call to perform the same operation.

Join preserves the order of the elements of outer, and for each of these elements, the order of the matching elements of inner.

In query expression syntax, a join (Visual C#) or Join (Visual Basic) clause translates to an invocation of Join.

In relational database terms, the Join method implements an inner equijoin. ‘Inner’ means that only elements that have a match in the other sequence are included in the results. An ‘equijoin’ is a join in which the keys are compared for equality. A left outer join operation has no dedicated standard query operator, but can be performed by using the GroupJoin method. See Join Operations.

Thanks, I hope this proves helpful to someone, as it was certainly eye-opening to me.

Maybe Monad Extensions

I learned a lot from my last foray into implementing my own Maybe Monad.  Apparently, it got noticed by and was actually useful to Derick Bailey, as it was one of the resources he used in his own personal exploration into Monads.  Of course, Derick did the topic a bit more justice, as he has a propensity to do.

Nonetheless, I have done as I said I would and reworked my Murray Monads into a cleaner, more concise implementation using extension methods, much like the implementation I introduced from Dmitri Nesteruk in the last post.  So without further ado, I’d like to introduce you to the MaybeMonadExtensions.

Monads 2.0 - “These Go To Eleven”

If you want to get an introduction to what Monads are and how I got to where I am today with this little library, then you really should check out the previous post on this topic.  I will however give a few brief code samples to show you what it can do to tidy up all those null checks using the Maybe Monad.

Here is code we tend to write all the time:

string postCode;
if (person != null)
{
  if (HasMedicalRecord(person) && person.Address != null)
  {
    CheckAddress(person.Address);
    if (person.Address.PostCode != null)
      postCode = person.Address.PostCode.ToString();
    else
      postCode = "UNKNOWN";
  }
}

It can look like this with some Maybe Monad love:

string postalCode = person.If(HasMedicalRecord)
  .Access(p => p.Address)
  .Apply(CheckAddress)
  .Access(a => a.PostCode)
  .Convert(pc => pc.ToString(), "UNKNOWN");

I know!  Groovy, huh?!

The source can be found here:  http://bitbucket.org/murrayondotnet/maybemonadextensions/

Let me know if you put this to good use!

Comments

Omer Mor
I see your point.
However, even Rx is sharing many LINQ operators with its IObservable & IQbservable monads.
So we already have 4 different monads (IEnumerable, IQueryable, IObservable, IQbservable) using those operators. I don't think any more would hurt :-)
Mike Murray
Great question. I suppose I could have used those names and it would likely be a familiar vernacular for .NET developers. I guess my only hesitation would be that I wouldn't necessarily want to confuse others who read the code into thinking that they are LINQ extension methods. My first thought when I saw your code was that somehow person was an IQueryable or IEnumerable, just because of those familiar method names.

Great point though, and it does make me second guess my chosen names a bit. I did like Derick's method names too (especially just plain old "Get"). Thanks for posting!
Omer Mor
Nice.

Why didn't you choose the Linq terminology here?
I'd write your example as this (Linq + Rx's Do operator):


string postalCode = person.Where(HasMedicalRecord)
.Select(p => p.Address)
.Do(CheckAddress)
.Select(a => a.PostCode)
.Select(pc => pc.ToString(), "UNKNOWN");

Maybe From Murray Monads

Off and on for the last six months, I have probably seen and read at least a half dozen introductions and tutorials on monads, a functional programming construct based on the mathematical monads from category theory.  Monads are known for their headache-inducing explanations, and I’ve had my fair share.  Every tutorial I’ve committed time to mentions the endless possibilities of using such constructs to improve your code, but I’ve had a hard time finding real-world examples of using this stuff out in the wild (much like this Stack Overflow poster, whose link I only found just now).  It has recently become a quest of mine to find some C# code we all write that could be improved by a monad.

I am now going to attempt to introduce a Maybe monad that I cooked up, but I warn you that I have no idea what I’m doing or if I’m staying within the rules for what makes a monad by definition a monad.  Don’t worry though, you have nothing to lose; I’m the only one taking a risk at looking foolish, and it’s all at the expense of my reputation and not yours.  Should be fun!

“It is not the spoon that bends, it is only yourself”

From the Wikipedia article linked to above:

“In functional programming, a monad is a kind of abstract data type constructor used to represent computations (instead of data in the domain model). Monads allow the programmer to chain actions together to build a pipeline, in which each action is decorated with additional processing rules provided by the monad. Programs written in functional style can make use of monads to structure procedures that include sequenced operations, or to define arbitrary control flows (like handling concurrency, continuations, or exceptions).

“A programmer will compose monadic functions to define a data-processing pipeline. The monad acts as a framework, as it’s a reusable behavior that decides the order in which the specific monadic functions in the pipeline are called, and manages all the undercover work required by the computation.”

The promised tenets of monads are increased code readability and algorithm composability, an example of preferring declarative code over imperative, procedural code.  In the case of the Maybe monad, it is a wrapper around types that might have an invalid state like null or nothing.  The lure of the Maybe monad is the ability to deal with values that might be in this invalid state without having to explicitly check for null before continuing or exceptions being thrown in your algorithms.

I first found a post by Rinat Abdullin where he introduced his version of a C# Maybe monad.  I downloaded the library and attempted to figure out how to use it in code I could possibly write any given day.  I tried mimicking the HttpContext.Request.Params collection commonly used in ASP.NET pages and HTTP handlers to retrieve the passed in query string or post values on the Request object.  If you ask that collection for a parameter that was not passed in on the request, it returns a null instead of the string value.  Common practice is to then use a bunch of if statements and key off the fact that certain query string or post parameters may or may not exist.

The problem I ran into with Rinat’s implemenation is that I wrote the code using the monad how I thought it should help me, and then ran into compiler errors and runtime exceptions because of the expectation that Maybe objects couldn’t be constructed around null values.  Here is the twitter conversation I had with Rinat in regard to this misconception that I had:

murrayondotnet's avatar
murrayondotnet says:
@abdullin Can you make your MaybeMonad in Lokad lib accept null at construct or explicit/implicit cast? Maybe<SomeType> monad = varThatsNull
abdullin's avatar
abdullin says:
@murrayondotnet No, this would violate the idea of MaybeMonad (as in Lokad libs). But you can copy code and tweak it to your needs locally.
murrayondotnet's avatar
murrayondotnet says:
@abdullin Figured this was case; what does it violate? I’m still new to monads. Thought one would be able construct monad around maybe null
abdullin's avatar
abdullin says:
@murrayondotnet check out the article on Maybe monads in Lokad libs: http://bit.ly/1GJlNN
murrayondotnet's avatar
murrayondotnet says:
@abdullin Thanks for the link, thats actually how I found your lib. I didnt see where you say why cant construct maybe monad on null. Help?
abdullin's avatar
abdullin says:
@murrayondotnet in essence monad in Lokad guarantees: there will be no nulls around (hence no need to check for them), it replaces null.
murrayondotnet's avatar
murrayondotnet says:
@abdullin I may try to create my own implementation that hides whether null or not. If so probably base mine off of the nice things in yours

And so I did.

Introducing MurrayMonads

I don’t even like the name.  I’m also not sure this code will ever be used again…by anyone, let alone me (especially since I like some other guy’s implementation better; read on to watch me embarrass myself).  But whatever, Visual Studio asks for a project/solution name and so there it is.  I need some cool theme like Rhino, as used by Ayende.

Speaking of Oren (I will use his proper name instead so that he doesn’t get stuck at the airport unable to board his flight), he posted a link on Twitter to an article where Dmitri Nesteruk created his own version of the Maybe monad, just as I was starting my experiment.  He used extension methods instead of an explicit monad object wrapper in order to enable the pipelining composability that you can also do with Rinat’s implementation.  Really clever, but there was one small thing that bothered me a bit, and that is how the monad chaining begins with Dmitri’s API.  (Actually, I’ll prove I’m wrong by the end of the post; this is the cause of upcoming embarrassment mentioned above, hooray!)  Because of this, I decided to use his example problem as the basis for my sample that I will show, in order to increase comparability.

So I set off to try and merge the good points of both Rinat’s and Dmitri’s implementations.  I have put my source code up for viewing at Bitbucket.org:  http://bitbucket.org/murrayondotnet/murraymonads

Are We There Yet?!

Yes, we are.  Let’s see some code finally.

Here is the code we don’t like writing all the time:

string postCode;
if (person != null)
{
  if (HasMedicalRecord(person) && person.Address != null)
  {
    CheckAddress(person.Address);
    if (person.Address.PostCode != null)
      postCode = person.Address.PostCode.ToString();
    else
      postCode = "UNKNOWN";
  }
}

This is actually code that you wrote; I took it just yesterday from your current project at work.  I know you’re feeling a bit defensive because of this, but I’m here to help so put down the attitude please.  We’re gonna make your life easier…I hope…

All in all, it’s code you see every day and there’s not much really wrong with it per se.  I just think it could be cleaner I suppose.  So using Dmitri’s extension methods, you can get that logic down to this:

string postCode = this.With(x => person)
  .If(x => HasMedicalRecord(x))
  .With(x => x.Address)
  .Do(x => CheckAddress(x))
  .With(x => x.PostCode)
  .Return(x => x.ToString(), "UNKNOWN");

As long as that last ToString method call doesn’t return a null (which one of my use cases does in the TestConsoleApp included in my source code), you will either get the value or “UNKNOWN”.  Looking good!

So my version of the Maybe monad comes out pretty close to this last one:

string postCode = person.If(p => HasMedicalRecord(p))
  .Access(p => p.Address)
  .Apply(a => CheckAddress(a))
  .Access(a => a.PostCode)
  .Convert(pc => pc.ToString(), "UNKNOWN");

// or even
string postalCode = person.If(HasMedicalRecord)
  .Access(p => p.Address)
  .Apply(CheckAddress)
  .Access(a => a.PostCode)
  .Convert(pc => pc.ToString(), "UNKNOWN");

The difference between Dmitri’s and mine being how the chain is first started, on the Maybe person object instead of Dmitri’s use of the this keyword.

Here’s what you’ve been really waiting for where I eat my own words.  Dmitri’s code can also be written like this:

string postCode = person.If(HasMedicalRecord)
  .With(x => x.Address)
  .Do(CheckAddress)
  .With(x => x.PostCode)
  .Return(x => x.ToString(), "UNKNOWN");

…which appears to take away any advantage of my library.  I officially like his solution better, I just don’t like some of the method names.  So perhaps I will create another blog post and Bitbucket repo with a new library of extension methods instead.  I will leave up this mess-of-a-post public (as well as the source code) so that perhaps others can see the process I went through and learn from my mistakes.

Your Turn to Criticize Now

Let me have it.  Let me know how crazy I am or if this is even useful.  Let me know if I’m completely misusing the monad principles.  Or, by some weird miracle, let me know if I’m on to something.  Actually, if Dmitri is on to something.  Either way, I want to hear from you.  Thanks.

Additional Monad Learning Resources

F# Pipeline Operator in C#?

I am currently reading the Real-World Functional Programming book from Manning Publications. It’s mostly an exercise in learning F#, but also to improve my C# code as well. I finally learned what the F# pipelining operator (|>) is all about, and I was so impressed I thought I would try to figure out how to bring it into C# if possible.

Introducing the F# Pipeline Operator

Here is some F# code that defines a list of integers and a pair of functions.  They are then used in a few “higher-order” functions (functions that utilize other functions as parameters or return values, according to my book).  List.filter is equivalent to the LINQ IEnumerable.Where() extension method, and List.map is equivalent to IEnumerable.Select().

let numbers = [ 1 .. 10 ]
let isOdd(n) = n % 2 = 1
let square(n) = n * n

List.filter isOdd numbers
List.map square (List.filter isOdd numbers)

The interesting part is the last line of code, where it is argued that you lose a little bit of code readability because the function that is actually executed first (List.filter) is found second in the expression statement.  Enter the F# pipelining operator:

let squared =
  numbers
  |> List.filter isOdd
  |> List.map square

Even though we’re no longer a compact, one-liner expression, I think we’ve gained some code readability.  It says to take the list numbers and perform the following manipulations in the exact order listed.  Cool stuff, if I say so myself.

“There is No Charge for Awesomeness…or Attractiveness”

(Sorry, I’ve been watching the movie Kung Fu Panda a lot with my kids lately.  Funny stuff.)  So can this awesomeness be brought over into C#?  I opened up Visual Studio and tried to see if I could figure out how to define my own operator or reuse one of the existing ones.

I realize C# is a pretty tough language to flip keywords and operators around and invent new syntax with (ok, it’s impossible), but I tried anyway.  The type of code readability issue I wanted to remedy is the same as with the F# code snippet above.  I thought it would be nice to make C# code like the following statement more readable and digestible (especially the execution order):

Convert.ToInt32(Context.Request[“requestParam”].Trim());

As I started to (unsuccessfully) beat out some pretty rough code, I ran into problems with trying to make extension methods that are operator definition overloads and errors saying “One of the parameters of a binary operator must be the containing type.”  It just wasn’t working and then I began to realize that C# already has a pipelining syntax, even if only in one small subset of the .NET API.  You can find a decent pipelining syntax with the Fluent Interface used for the LINQ extension methods.  Its power is in the fact that the functions return the object type that was passed in and acted upon, so that more functions can be chained on afterward in a composable manner.  The ability to do things like collection.Where().Select().OrderBy() is a much more declarative and functional solution to imperative for loops (and it makes it more readable and intention revealing in my opinion).  It’s a difference in describing more what you want to be accomplished rather than how it is to be accomplished (especially when the how in programming languages is more readable to a computer than it is a human).

So the good news is that you indeed can have a nice pipelining syntax in C#, especially for APIs that are designed with Fluent Interfaces like LINQ.  However, it doesn’t solve code readability issues with code snippets like the C# fragment I showed above.  For those regular, non-fluent method calls in the rest of the .NET API, you must use old-fashioned Object-Oriented Programming practices of breaking code up into meaningful, atomic units of statements and naming and encapsulating functions cohesively in order to get more readable code.

Comments

Jonas Elfström
This looks a whole lot like the Thrush Combinator.
I implemented that one in C# a while ago
Richard Beauchamp
This comment has been removed by the author.
Mike Murray
Funny you should mention the Maybe Monad, as I've been looking into Monads off and on for several months trying to figure out how I could use them in everyday code. I likely will be posting something on this in the somewhat near future.
Anonymous
Just a small hint from someone who uses something like this in productive code on a day-to-day basis:

Take your time and extend the static methods a bit. It won't hurt to build something like a maybe-monad in there.

You know - check if the input is null and return null if so.

For this you need either:
- "where U : class"
- use Equals

For the same reason I give somethink like a "DefaultValue" Funktion that checks the input for null and responses with the default-value if so, if not it will give the original value.
Mike Murray
Very intriguing! Man I wish I had thought about that. I suppose I'm still new to designing APIs that pass around Funcs.

I was able to make the following code work with the type inference (and without having to specify the types to the Then method):

var blah = "576 "
.Then(x => x.Trim())
.Then(x => Convert.ToInt32(x));

Not too bad really. A little too much C# syntax though, but I'd argue it might be more readable than what we started with, the code everyone writes. It appears my code snippet doesn't even need the second extension method.

Thanks for sharing!
Yusuf Motara
You could try this:

static class Extn {
public static U Then<T,U>(this T o, Func<T, U> f) { return f(o); }
public static U Then<T, U>(this T o, Func<T, Func<U>> fe) { return fe(o)(); }
}

… which lets you write the more-readable:

var blah = "576 "
.Then<string,string>(x => x.Trim)
.Then(Convert.ToInt32);

Unfortunately, it seems that you need to make the generic parameters explicit; C#'s type inference is nowhere near as good as F#'s.

Reactive Framework Finally Explained

I have been intrigued by the Reactive Extensions for .NET (Rx Framework) for quite a while now, especially the fundamental shift from a “push” data model as opposed to the “pull” model most familiar to us.  I have thought to myself that this must be a game changer in how data and events are consumed in every-day software.  I didn’t quite understand how it all works or how to use it from the few samples I had seen, but I knew if I gave myself a little time to really sit down and look at it, my life would be changed forever.

However, after reading some articles, watching some recorded presentations, and even attending a MIX ‘10 session in-person on the Reactive Extensions, I felt increasingly lost and confused by what this framework could offer me.  I wasn’t understanding some fundamental ideology of the framework and it was jading my learning experience when watching/reading sample code.  Well, I think I have finally figured out what the mental roadblock was and will attempt to explain the framework here as I best as I understand it, in hopes that it can be of help to others not getting what the fuss is all about.  I can sense that I’m not the only one who has been turned off by the unsuccessful attempts by Microsoft to explain this revolutionary framework to the average developer.  Apparently those who had a hand in designing the framework are just so incredibly intelligent that they are having a hard time discerning that the common man is not immediately getting it.

IEnumerable<T>, Meet IObservable<T>

Essentially what Microsoft did is create a mathematical dual of the IEnumerable and IEnumerator interfaces using Category Theory, and named them IObservable and IObserver respectively.  In its bare simplicity, this is done by merely reversing the direction of your arrows in your mathematical functions and compositions.  The following images of a few slides from Erik Meijer’s MIX ‘10 Session that were the best visual explanation I have seen:

Duality Example with De Morgan’s Laws

rxSlide2

Creating a Dual of IEnumerable

rxSlide3

Creating a Dual of IEnumerator

rxSlide4 

The reason the mathematical proof part is significant is because we can guarantee that LINQ syntax and operators will work on these new collection and data subscriber interfaces, just like they did with IEnumerable collections in LINQ-to-Objects.  This new LINQ provider is commonly called “LINQ over Events.”

Reacting to Data is Asynchronous

This is actually where I think some of the confusion came in for me.  Mostly what I didn’t understand is how you can write LINQ queries into pushed data (already sent and also yet to be sent), when essentially that task is indeterminate by nature.  What I have figured out is that the LINQ syntax is not entirely for the data being pushed, but also used for molding the subscriptions themselves.  What the LINQ syntax provides you is a way to compose, filter, project, aggregate, and throttle data and event subscriptions in a powerful, declarative way.

A common workflow seems to be to create one or more observable collections (and there are many ways to do so) and then customize and compose a subscription based on the subscription(s) using LINQ syntax.  All that’s left then is to set the subscription in motion, giving it some sort of callback or lambda expression to be called as data is asynchronously pushed in and processed.

Here is a very simple code example that illustrates this process quite plainly:

using System;
using System.Linq;

namespace TestRX
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var oneNumberPerSecond = Observable.Interval(TimeSpan.FromSeconds(1));

            var numbersTimesTwo = from n in oneNumberPerSecond
                                  select n * 2;

            Console.WriteLine("Numbers * 2:");

            numbersTimesTwo.Subscribe(num =>
            {
                Console.WriteLine(num);
            });

            Console.ReadKey();
        }
    }
}

It is interesting to watch the code run and think about what it’s actually doing.  It sits on the Console.ReadKey() line while the observable collection is asynchronously pushing data to the lambda expression containing the Console.WriteLine() statement.

It looks like the Reactive Framework is not just a better way to handle events and pushed data, but it also appears from what I’ve read that it could be used as a nicer API for sending off asynchronous process threads.

Additional Reading

Microsoft DevLabs has created the Reactive Extensions for .NET (and it’s associated languages), but it has also came up with the Reactive Extensions for Silverlight and JavaScript (can be found on same webpage).  This proves very interesting as JavaScript (and Silverlight) tends to be quite event driven because of its close interactions to UI elements in HTML (or XAML).  In fact, one of the most encouraging example use cases that I’ve heard was that of having some HTML text field that you wanted to auto-search as the user types, but not until the user pauses for a second; they can also hit Enter.  What the Reactive Framework could provide you is a way to aggregate more than one event source (alphabetic and Enter key strokes and the timer) into a single event handler using clear, declarative framework statements.

Here are other links I would recommend for additional examples and explanation:

Enjoy!  Let me know via comments if you start using it for something real cool and useful.

Comments

Michael
Nice post on a complex topic. You are indeed correct that there has been confusion around explaining the why and how of Reactive Extensions. Thanks Mike.
Paul
Great post on getting started with Rx! One of the things I've been working on is a MVVM framework for Silverlight / WPF that uses the Reactive Extensions - I've written about it quite a bit in my blog at http://blog.paulbetts.org/index.php/category/programming/reactive-extensions/ and the code is at github.com/xpaulbettsx/ReactiveXaml ; it's got some great examples of doing more than just handling events together, I'd love to hear any feedback you've got on the project