views:

1663

answers:

9

I've got the following (simplified):

interface IFindFilesObserver
{
    void OnFoundFile(FileInfo fileInfo);
    void OnFoundDirectory(DirectoryInfo directoryInfo);
}

class FindFiles
{
    IFindFilesObserver _observer;

    // ...
}

...and I'm conflicted. This is basically what I would have written in C++, but C# has events. Should I change the code to use events, or should I leave it alone?

What are the advantages or disadvantages of events over a traditional observer interface?

+10  A: 

Hmm, events can be used to implement the Observer pattern. In fact, using events can be regarded as another implementation of the observer-pattern imho.

Frederik Gheysels
Absolutely. This is a bit like asking, "Should I implement the iterator pattern or use foreach and IEnumerable?"
Jon Skeet
Events being fired from your observer is a natural way to notify multiple consumers of a change in the application
JoshBerke
I know that this is the observer pattern; I asked whether I should implement the pattern using a callback interface or by using events.
Roger Lipscombe
+2  A: 

Pros are that events are more 'dot-netty'. If you are designing non-visual components that can be dropped onto a form, you can hook them up using the designer.

Cons are that an event only signifies a single event - you need a separate event for each 'thing' that you want to notify the observer about. This doesn't really have much practical impact except that each observed object would need to hold a reference for every observer for every event, bloating memory in the case where there are lots of observed objects (one of the reasons they made a different way of managing the observer/observable relationship in WPF).

In your case I'd argue it doesn't make much difference. If the observer would typically be interested in all those events, use an observer interface rather than separate events.

U62
Well there's nothing stopping you to have a single c# event that differentiates different events by a child class of EventArgs - I wouldn't do that though.
DrJokepu
+17  A: 

Consider an event to be a callback interface where the interface has only one method.

Only hook events you need
With events you only need to implement handlers for events you're interested in handling. In the observer interface pattern, you'd have to implement all methods in the entire interface including implementing method bodies for notification types you don't actually care about handling. In your example, you always have to implement OnFoundDirectory and OnFoundFile, even if you only care about one of these events.

Less maintenance
Another good thing about events is you can add a new one to a particular class so that it will raise it, and you don't have to change every existing observer. Whereas if you want to add a new method to an interface, you have to go around every class that already implements that interface and implement the new method in all of them. With an event though, you only need to alter existing classes that actually want to do something in response to the new event you're adding.

The pattern is built into the language so everybody knows how to use it
Events are idiomatic, in that when you see an event, you know how to use it. With an observer interface, people often implement different ways of registering to receive notifications and hook up the observer.. with events though, once you've learnt how to register and use one (with the += operator), the rest are all the same.

Pros for interfaces
I haven't got many pros for interfaces. I guess they force someone to to implement all methods in the interface. But, you can't really force somebody to implement all those methods correctly, so I don't think there's a lot of value on this.

Syntax
Some people don't like the way you have to declare a delegate type for each event. Also, standard event handlers in the .Net framework follow have these parameters: (object sender, EventArgs args). As sender doesn't specify a particular type, you have to down-cast if you want to use it. This often is fine in practice, if feels not quite right though because you're losing the protection of the static type system. But, if you implement your own events and don't follow the .Net framework convention on this, you can use the correct type so potential down-casting isn't required.

Scott Langham
A small pro for interfaces is that when you have a lot of events that usually come together you don't have to register them all in a huge block of event +=s, but only register that one interface. I still prefer events though, of course :)
configurator
One con for events is that they don't fire across app domains. If you app is (or will be) complex, this will become an issue.
TMN
+2  A: 

Pros of an interface-solution:

  • If you add methods, existing observers needs to implement those methods. This means that you have less of a chance of forgetting to wire up existing observers to new functionality. You can of course implement them as empty methods which means you have the luxury of still doing nothing in response to certain "events". But you won't so easily forget.
  • If you use explicit implementation, you'll also get compiler errors the other way, if you remove or change existing interfaces, then observers implementing them will stop compiling.

Cons:

  • More thought has to go into planning, since a change in the observer interface might enforce changes all over your solution, which might require different planning. Since a simple event is optional, little or no other code has to change unless that other code should react to the event.
Lasse V. Karlsen
A: 

I prefer an event base solution for the following reasons

  • It reduces the cost of entry. It's much easier to say "+= new EventHandler" than to implement a full fledged interface.
  • It reduces maintenance costs. If you add a new event into your class that's all that needs to be done. If you add a new event to an interface you must update every single consumer in your code base. Or define an entirely new interface which over time gets annoying to consumers "Do I implement IRandomEvent2 or IRandomEvent5?"
  • Events allow for handlers to be non-class based (ie a static method somewhere). There is no functional reason to force all event handlers to be an instance member
  • Grouping a bunch of events into an interface is making an assumption about how the events are used (and it's just that, an assumption)
  • Interfaces offer no real advantage over a raw event.
JaredPar
+1  A: 

Java has language support for anonymous interfaces, so callback interfaces are the thing to use in Java.

C# has support for anonymous delegates - lambdas - and so events are the thing to use in C#.

Daniel Earwicker
A: 

The best way to decide is this: which one suits the situation better. That might sound like a silly or unhelpful answer, but I don't think you should regard one or the other as the "proper" solution.

We can throw a hundred tips at you. Events are best when the observer is expected to listen for arbitrary events. An interface is best when the observer is expected to listed to all of a given set of events. Events are best when dealing with GUI apps. Interfaces consume less memory (a single pointer for multiple events). Yadda yadda yadda. A bulleted list of pros and cons is something to think about, but not a definitive answer. What you really need to do is try both of them in actual applications and get a good feel for them. Then you can choose the one that suits the situation better. Learn form doing.

If you have to use a single defining question, then ask yourself which better describes your situation: A set of loosely related events any of which may be used or ignored, or a set of closely related events which will all generally need to be handled by one observer. But then, I'm just describing the event model and interface model, so I'm back at square one: which one suits the situation better?

Snarfblam
That's why I asked for pros/cons. I realise that there's no "one size fits all" solution. It was just something I was weighing up and thought it'd be an interesting question.
Roger Lipscombe
+5  A: 

Some further benefits of events.

  • You get proper multicast behaviour for free.
  • If you change the subscribers of an event in response to that event the behaviour is well defined
  • They can be introspected (reflected) easily and consistently
  • Tool chain support for events (simply because they are the idiom in .net)
  • You get the option to use the asynchronous apis it provides

You can achieve all of these (except the tool chain) yourself but it's surprisingly hard. For example: If you use a member variable like a List<> to store the list of observers. If you use foreach to iterate over it then any attempt to add or remove a subscriber within one of the OnFoo() method callbacks will trigger an exception unless you write further code to deal with it cleanly.

ShuggyCoUk
A: 

A benefit of interfaces is that they are easier to apply decorators to. The standard example:

subject.RegisterObserver(new LoggingObserver(myRealObserver));

compared to:

subject.AnEvent += (sender, args) => { LogTheEvent(); realEventHandler(sender, args); };

(I'm a big fan of the decorator pattern).

Andreas