Observable event subscription

The other day I was trying to create an explicit interface implementation of an event and ran into a snag. Now I've done many explicit interface implementations before, but, I guess, never of an event, because I'd not seen the below compiler error before:

An explicit interface implementation of an event must use property syntax

Huh? I did some searches on that error and the best reference was this page. I had long forgotten that the whole += and -= was closely related to how properties work. But instead of using get and set you can create your own logic for subscribe and unsubscribe using add and remove.

As Oliver points out on his blog, it does mean that your event just becomes a facade and you still need another event that actually is being subscribed to. So for that explicit interface implemenation you'd get something like this:

interface IFoo
{
   event EventHandler FooHappened;
}

class SomeClass : IFoo 
{
  private event EventHandler internal_FooHappened;

  public event EventHandler IFoo.FooHappened
  {
    add { internal_FooHappened += value; }
    remove { internal_FooHappened -= value; }
  }

  private void OnFooHappened()
  {
    if( internal_FooHappened != null )
    {
      internal_FooHappened(this,EventArgs.Empty);
    }
  }
}

Now this is really an edge case, imho. But the same syntactic trick does allow for something else that's pretty cool, i.e. being able to be notified when someone subscribes to your event. I've had it happen a number of times, where it would have been useful to take some action on subscription. Maybe the event needs some extra resource, that you don't want to initialize unless someone needs it. It may even be that the real event handler is that resource. So now you can use the above syntax and put extra logic inside of the add to initialize that resource, like this:

class SomeClass
{
  SomeResource myResource;

  public event EventHandler FooHappened
  {
    add
    {
      if( myResource == null )
      {
         myResource = new SomeResource();
      }
      myResource.FooHappened += value;
    }
    remove
    {
      myResource.FooHappened -= value;
      if( myResource.FooHappened == null )
      {
         myResource.Dispose();
         myResource = null;
       }
    }
  }
}