In situations where I need to write observer/subscriber code, how would I choose between the following approaches?

A) Declaring an event that simply notifies a client something happens but requires the client to make a query for data e.g.

class SoothSayer{

    int DaysUntilApocalypse{get;}

    event EventHandler<EventArgs> TheEndIsNigh;


B) Declaring an event with specific XXXEventArgs containing the event data e.g.

class SoothSayer{

    event EventHandler<ApocalypsePendingEventArgs> TheEndIsNigh

class ApocalypsePendingEventArgs:EventArgs{
    int DaysLeft{get;}

C) Using a callback rather than an event e.g.

class SoothSayer{

    public SoothSayer(Action<int> endIsNighCallback){
        _endIsNightCallBack = endIsNighCallback;
  • I've tried to fix the title; I think the "subscribe" terminology was throwing people off (one answer has now been submitted which really had nothing to do with the question).
    – Aaronaught
    Commented Jun 9, 2011 at 20:22

3 Answers 3


Version (c) is a form of continuation passing, it is not an event at all. It is a wholly different method of control flow, and can be used to express some complex types of control flow that are difficult to express with primitive constructs such as loops and conditionals. For example, it's the basis for asynchrony in C# 5. All await really does, in essence, is pass a continuation.

It is certainly a valid construct, but the answer to when you should use this for event-driven programming is never, because it's not an event. There is no subscription of any kind; the callback is coupled to method call. You also can't have multiple subscriptions, which you can have with any old event.

So it comes down a choice between (a) using a plain EventHandler or (b) using a custom MyEventHandler with event data. And the answer to that is simple: use a custom event if there is important, transient data associated with the event.

Imagine if you had to query for the cursor position every time you executed a MouseDown event handler. It would be completely unreliable, because the mouse position could and often would change between the time the event was fired and the time it was handled. On the other hand, an Initialized event is pretty self-explanatory; it's only going to happen once in the lifetime of an object and there's really not much else to say about it other than "OK, I'm ready!".

So, in summary, (a) use the default EventHandler when you've got nothing else interesting to say, (b) use a strong-typed EventHandler<T> when you do, and (c) don't use CPS for event notifications.

  • P.S. I used pub/sub as a clarification to the odd original "observer/subscribe" wording; however, the term "pub/sub" is normally used more often when describing architectures. Event-driven programming or even just event notification would probably be a more appropriate term.
    – Aaronaught
    Commented Jun 9, 2011 at 1:35
  • Thanks, that's a really helpful answer. The programming I've been doing so far isn't that complex and hasn't required me to raise events with transient data, though I've seen lot's of examples in the .Net framework and especially in WPF, but I don't think I'll forget the distinction now that you've flipped the switch in my brain. Also nice to discover some new terminology, i.e. CPS.
    – Grokodile
    Commented Jun 9, 2011 at 16:13

I guess the Question itself has got answer. That depends on the scenario.

If you intend just a notification od a particular thing happened and the subscriber has all the data (or does not require any more data from publisher, at the least), then use Method A

if you want to pass some data that the publiser only has , also which is needed by the subcriber Use Method B

Giving some pseudo code for a hypothetical scenario:

 Class ClosedRoom

      event: RoomOverHeatingHappened//notification
      event: RoomOptimalTemperatureReached//notification

      event: WindowOpenedOrClosed(int WindowNumber,Bool isOpened)//it notifies + tells which of the 4 windows got opened/closed + whether it is opened or closed


So event based programming is not really messaging. Messaging frameworks exist within .NET, but aren't hugely abundant. Messaging normally leads to Actors http://en.wikipedia.org/wiki/Actor_model. Actors are a totally different way to deal with systems (and often make multi-threaded software much easier) than just some basic eventing.

https://github.com/phatboyg/stact Actor framework

http://msdn.microsoft.com/en-us/devlabs/dd795202 Axum is Microsoft shuttered actor compiler

http://code.google.com/p/retlang/ Sorta messaging/actor framework

  • thanks for the reply, I'm not really sure how you're interpreting my question, I was asking about the issue at C# language level rather than the framework level, are the things you're suggesting similar to the GO4 Mediator pattern?
    – Grokodile
    Commented Jun 9, 2011 at 22:20
  • You were asking about publish/subscribe, which is messaging. You've since changed the question so it doesn't really apply any more. Aaronaught's response is a useful one and hopefully resolves your question.
    – Travis
    Commented Jun 9, 2011 at 23:44
  • no problem, I didn't realise that publish/subscribe was a specific term for something at a higher level, I originally termed the question Observer\Subscriber (in itself incorrect) as I was thinking of the .Net event pattern as an implementation of the GO4 Observer.
    – Grokodile
    Commented Jun 10, 2011 at 0:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.