tl;dr: Why are field-like events implemented as a single delegate field? Wouldn\
ID: 646057 • Letter: T
Question
tl;dr: Why are field-like events implemented as a single delegate field? Wouldn't it be more straight-forward to use a list of delegates, thereby eliminating the null special case and avoiding all the MulticastDelegate magic?
The usual pattern to raise field-like events (ignoring synchronization issues for the moment) is
if (MyEvent != null)
MyEvent(this, e);
which can be quite confusing (Why do I have a null check for 0 handlers, but no loop for multiple handlers?), until you understand how field-like events are implemented and that MyEvent refers to an automatic backing field which can contain either null, a single delegate or a MulticastDelegate holding references to multiple handlers.
On a first glance, this seems to be a strange design choice. In particular, the obvious alternative would be to use a list of simple delegates, which is how the Observer pattern is commonly implemented in languages such as Java. True, the invocation would be slightly longer:
foreach (var handler in MyEvent)
handler(this, e);
but it would be easier to understand (in my subjective opinion) and probably easier to implement (no need for all the delegate multicasting logic).
Obviously, the C# designers thought otherwise. Since they are a bunch of very smart people, there must have been a good reason for it. What is it?
Explanation / Answer
All delegates are effectively lists. The empty list is null, but you can still append to it with +=.
The need to check for null before calling is very inconvenient, yes. But does not occur because they are not lists! It occurs because of how the empty list is represented.
However you can avoid this by initialising the event:
public event EventType MyEvent = delegate {};
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.