I revisited your question after looking at your last question.
First note is: all, absolutely
all delegate instances in .NET are multicast. I mean, some delegate instances have only one handler in its invocation list, but in all such cases "+=" creates a multicast interface instances with two handlers. They all have an invocation list as a member, even each member of invocation list, paradoxically. What is interesting, "+=" never adds anything to existing delegate instance:
delegate instances are immutable. A brand-new delegate instances and a brand new reference to it is created in response to "+=". The immutability of delegate instance is done to improve multithreading. Finally, why do I talk about delegate instances? Take a type of a delegate instance.
Is it a delegate type? No! A run-time type of a delegate instance is some… class. Get a type and use Reflection to see. I write about it in my article
Dynamic Method Dispatcher[
^].
Now, let's move to events. Here is my statement: each and every behavior of events can be implemented using just delegate and delegate instances, without any exclusion. Not visa versa.
So, what's the benefits of events over delegate instances? Limitations!
For example: whatever you do, you can invoke event only in its declaring class, nowhere else. You cannot even invoke an event in a derived class, which is very unusual, because in other cases, every possibility is dictated by access modifiers and scope, nothing else. Why is that? I understood it well answering CodeProject questions. Many asked: "how can I call (I say: "invoke, not call" — SA) the event
Button.Click
?".
(Amazing logic: when a compiler says: "operation X is not allowed", typical first question is "how to do operation X"? We have a proverb: "If prohibited but very desirable then allowed" :-).)
The event
Button.Click
is already invoked — in the libraries. Invocation of it somewhere else, even through a class derived from
Button
is never really needed; one can always call some method in two places: from the
Button.Click
handler and somewhere else, but it would not cause invocation (which would cause the call of each handler in the invocation list), and hence it would not disrupt intended behavior of UI event system.
Invocation of this event would be foolish. And the event is what it is:
a fool-proof variant of delegate instances.
And UI is not the only field of application of events.
Events are used when the limitations of events are needed.
—SA