I really do like C# Events.
In several other popular object oriented programming languages, the only option to decouple callback functionality is to introduce another class or interface that needs to be implemented by the caller.
For example, in the Mac OS X and iOS user interface APIs, all callback functionality is implemented by Delegate classes (or protocols), of which there is one for each user interface class. These Delegate classes often need to implement a bunch of unrelated functionality that may clog up your classes.
On the other hand, the C# Event – a method call chain – allows for a fine grained and simpler binding.
C# Event handlers can be distributed to different classes. For example, for a user interface table control there could be one class handling all selection events and another one rendering the rows.
But nothing comes without a drawback. Binding to an event always introduces a bidirectional relationship with the class in question. Without clearly knowing the lifetime of the controls and their related event handlers, memory leaks are preprogrammed. To avoid them, event handling classes need to follow a strict symmetry. They should unbind themselves when their viewing component is no longer used. And C# the explicit Dispose() pattern fits nicely in that model.