There is no denying events in C# are a great step forward from more traditional approaches where a lot of boilerplate code needed to be written. I choose C# events over Java’s solution to the Observer pattern any day.
… but, there is one pesky little issue I have with them. By design, it’s really easy to introduce bugs using them. How often have you encountered a NullReferenceException because you didn’t check whether an event handler was null prior to calling it? As a more experienced developer you might choose one out of the following two options.
1. Repeated null checks
Always check whether an event isn’t null prior to calling it. Additionally, you need to copy the event handler to a local variable, otherwise another thread might unsubscribe from the event causing the handler to be null again after you did the null check.
EventHandler handler = SomeEvent;
if ( handler != null )
{
handler( ... );
}
2. Always subscribe one empty delegate
There might be a small cost of constantly having to call one extra function when the event is raised, but it solves the problem of having to do repeated null checks throughout the code while simultaneously solving the multi-threading issue.
public event EventHandler SomeEvent = delegate {};
The Aspect way
I prefer the second approach, and don’t see any reason why it shouldn’t be used by default, other than a smarter compiler which could take care of this in a ‘cleaner’ manner. That’s why over the weekend I’ve spent some time seeing how PostSharp could help solving this cross-cutting concern. I always love showing off the result prior to explaining how I got there. It’s usage is a one liner.
[assembly: InitializeEventHandlers( AttributeTargetTypes = "Laevo.*" )]
namespace Laevo { ... }
Adding this one attribute prevents you from having to worry about events throughout the entire namespace it applies to.
How does it work?
First of all, you will need PostSharp. That’s not necessarily a bad thing, because if you are fortunate enough to be allowed to use it, or you can simply decide for yourself to buy it, you will greatly appreciate it for more than just this one possible use case.
The InitializeEventHandlersAttribute is called an aspect which is applied on events. However, using a feature of PostSharp called ‘multicasting’, you are able to apply the attribute (MulticastAttribute) on higher level elements, allowing you to choose which one of the lower level elements the aspect should apply to. In the code above, the aspect is applied on an entire assembly, but the aspect knows it should only be applied to events, which is further narrowed down using the AttributeTargetTypes parameter to events within the namespace “Laevo”, and all sub-namespaces. In order to remind the developer that a certain part of his code is enhanced by an aspect, a visualization as follows is visible within Visual Studio.

The code is short enough to paste in its entirety now, but I’ll decompose it in a minute.
[AttributeUsage( AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Event )]
[MulticastAttributeUsage( MulticastTargets.Event, AllowMultiple = false )]
[AspectTypeDependency(
AspectDependencyAction.Commute,
typeof( InitializeEventHandlersAttribute ) )]
[Serializable]
public class InitializeEventHandlersAttribute : EventLevelAspect
{
[NonSerialized]
Action<object> _addEmptyEventHandler;
[OnMethodEntryAdvice, MethodPointcut( "SelectConstructors" )]
public void OnConstructorEntry( MethodExecutionArgs args )
{
_addEmptyEventHandler( args.Instance );
}
IEnumerable<ConstructorInfo> SelectConstructors( EventInfo target )
{
return target.DeclaringType.GetConstructors(
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
}
public override void RuntimeInitialize( EventInfo eventInfo )
{
base.RuntimeInitialize( eventInfo );
// Construct a suitable empty event handler.
MethodInfo delegateInfo = DelegateHelper.MethodInfoFromDelegateType(
eventInfo.EventHandlerType );
ParameterExpression[] parameters = delegateInfo.GetParameters().Select( p =>
Expression.Parameter( p.ParameterType ) ).ToArray();
Delegate emptyDelegate = Expression.Lambda(
eventInfo.EventHandlerType, Expression.Empty(),
"EmptyDelegate", true, parameters ).Compile();
// Create a delegate which adds the empty handler to an instance.
_addEmptyEventHandler = instance => eventInfo.AddEventHandler( instance, emptyDelegate );
}
}
The steps I followed to create this aspect are documented in the PostSharp 2.1 Documentation “Adding Behaviors to Members”.
- Create a new class, deriving from the relevant aspect class. Since I am creating an aspect which is applied on events, I used EventLevelAspect.
- Choose on which part of the code your aspect will have effect. This is called an ‘advice’. Although my aspect is applied on events, the solution I used is to add an empty event handler to the events by default. This is something which can be done from the constructor. Therefore I had to use an OnMethodEntryAdvice in order to add this code to the beginning of every constructor.
[OnMethodEntryAdvice, MethodPointcut( "SelectConstructors" )]
public void OnConstructorEntry( MethodExecutionArgs args )
{
_addEmptyEventHandler( args.Instance );
}
- Choosing a ‘pointcut’ is required to determine where the code needs to be added. We’ve already established it needs to be added to the start of methods by using OnMethodEntryAdvice, but we haven’t established which methods it needs to be applied to yet. By using a MethodPointcut, this task is delegated to a separate method of which you pass the name. In my case, this method doesn’t do much more than returning all the constructors of the current type.
IEnumerable<ConstructorInfo> SelectConstructors( EventInfo target )
{
return target.DeclaringType.GetConstructors(
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic );
}
- We are nearly done, although there is one part of the code I skipped over which is quite interesting nonetheless. The OnMethodEntryAdvice calls the delegate _addEmptyEventHandler(), but where did this come from? Overriding RuntimeInitialize gives you the chance to initialize objects which the advice will require for the specific element the aspect applies to. Using reflection to analyze the passed EventInfo object, a suitable empty event handler can be constructed using Expression Trees. This is required since we don’t have the luxury of using an equivalent to ‘delegate {}’. Finally a simple delegate is created which can add the empty delegate to the event of any given instance.
public override void RuntimeInitialize( EventInfo eventInfo )
{
base.RuntimeInitialize( eventInfo );
// Construct a suitable empty event handler.
MethodInfo delegateInfo = DelegateHelper.MethodInfoFromDelegateType( eventInfo.EventHandlerType );
ParameterExpression[] parameters = delegateInfo.GetParameters().Select( p => Expression.Parameter( p.ParameterType ) ).ToArray();
Delegate emptyDelegate
= Expression.Lambda( eventInfo.EventHandlerType, Expression.Empty(), "EmptyDelegate", true, parameters ).Compile();
// Create a delegate which adds the empty handler to an instance.
_addEmptyEventHandler = instance => eventInfo.AddEventHandler( instance, emptyDelegate );
}
… and all that just to eliminate ‘= delegate {}’? Yes, I can be quite stubborn sometimes. 🙂
UPDATE:
This code has since been slightly altered in order to also support events with generic parameters within generic types. Thank you Anupheaus, for reporting this issue! Be sure to check out the latest code on github. A discussion of the problem, and how to work around it can be found in my answer on Stack Overflow.