In C#, events and event listeners have direct support within the language, with event
being a keyword, and event declarations being a special kind of member declaration in a class.
The language documentation lists three language design goals for events:
- Enable very minimal coupling between an event source and an event sink. These two components may not be written by the same organization, and may even be updated on totally different schedules.
- It should be very simple to subscribe to an event, and to unsubscribe from that same event.
- Event sources should support multiple event subscribers. It should also support having no event subscribers attached.
However, all three of these goals could very well be met by implementing event listeners as a class or interface in the standard library, with Subscribe
, Invoke
and Unsubscribe
methods (and overloaded +
and -
operators to support +=
and -=
for subscribing and unsubscribing), and then user-defined classes could have fields for their event listeners, rather than events being a distinct kind of class member.
Typically, there is a preference for designers to implement features in the standard library when possible, rather than as intrinsics, to keep the compiler and the language specification simpler. Also, using a standard interface would allow alternative implementations to be provided (which might offer different guarantees with respect to order of execution, or threading) without unduly privileging one implementation as an intrinsic with special syntax. Additionally, having event
as a keyword makes it more awkward to use as an identifier (as an identifier it must be spelled @event
), and if event listeners are just objects then you can pass around references to them, which can be useful for some purposes.
So, why did the C# designers choose to make event listeners an intrinsic language construct?