I'm playing around with Reactive Extensions (Rx) at the moment, so expect a few themed posts.

    Observable.FromEvent<KeyEventHandlerKeyEventArgs>(e => textBox1.KeyUp += e, e => textBox1.KeyUp -= e)

Yuck. What's the deal with this? Why do we have to write out this boilerplate? Well, we don't, we also have the option of writing this:

    Observable.FromEventPattern(textBox1, "KeyUp")
But this has its own drawbacks: there's no type information for the event (you still have to add that manually if you want it) and it uses reflection to get at the event (no compile-time checking and a potential performance problem if you do this more than once).

The problem is that events are not first-class citizens in C#, but syntactic sugar for automagically implemented delegate properties. It would be nice if events at least offered a way of getting type information at compile time, but they don't. The only operations available on an event are adding a handler (through +=) and removing one (through -=). If nothing else, C# 5 should at least strongly consider offering another operation: .ToObservable(). Then you could write:


Which would just be syntactic sugar for Observable.FromEvent(), with the compiler filling in the boilerplate. I'm not sure if this can be made to work properly for events that flout convention and don't utilize EventArgs, but EventArgs should have full support from the .ToObservable()-conversion.

A slightly more daring approach would be to promote events to first-class citizens outright and introduce a class Event that all events are considered instances of. This class would be instantiated by compiler-generated code only -- I'm not brave enough to think of dynamically constructing events -- and offer the .AddHandler(), .RemoveHandler() and .ToObservable() operations. Again, EventArgs probably ruins things somehow by complicating delegate type handling (and the return type of .ToObservable()).

No comments: