I'm reading this article by Jon Skeet as part of my quest to get a deep understanding of delegates and events.
In the article he demonstrates an event that isn't backed by a delegate variable and states that...
...there are times when you don't want to back an event with a simple delegate variable. For instance, in situations where there are lots of events but only a few are likely to be subscribed to, you could have a map from some key describing the event to the delegate currently handling it. This is what Windows Forms does - it means that you can have a huge number of events without wasting a lot of memory with variables which will usually just have null values.
I don't fully understand what he is saying. Can someone flesh out the examples? For instance, what does he mean by having a "map from some key describing the event to the delegate currently handling it"? How does Windows Forms do this?
Thanks!
You can use the same type yourself -
EventHandlerList
. Suppose you have 100 events - that would normally mean having 100 variables, which would take up space even if no-one ever subscribed to the event. Instead of that,EventHandlerList
is a bit like aDictionary<object, EventHandler>
- it only creates an entry in its internal data structures when you first subscribe to a particular event.So you might have something like:
I'd like to add that this is something I've seen quite often
I consider this an anti-pattern because this way is quicker, takes less memory and is overall simpler I think:
Another situation is the trivial case, where a base class or interface provides an event for something that will never happen in certain derived types. For example, a read-only observable-collection interface might provide a CollectionChangedEvent. An entity holding an interface variable wouldn't be able to use it to change the collection, but might be interested in knowing if/when something else changes the collection. Such an entity should be able to use an immutable collection just as well as a mutable one; from its perspective, an immutable collection should be just like a mutable collection that nobody bothers to mutate while it's watching.
The most logical implementation of the CollectionChangedEvent would be to have add- and remove-handler methods that do nothing, with no backing delegate field. An outside entity that calls the add-handler method is essentially saying "Call me if this collection changes". When it calls the remove-handler method, it's essentially saying "I no longer need to know if this collection changes". If the collection is never ever going to change, those requests can be honored by simply doing nothing.