Raising Custom Events

Earlier today I was wading through the code for the Microsoft Sync Services (many thanks to Lutz Roeder’s Reflector and the file disassembler addin) so that I could understand how it all pieces together.  One of the interesting things I noticed was that in a couple of places they had appeared to write their own custom events which look a bit like:

public event EventHandler<ApplyChangeFailedEventArgs> ApplyChangeFailed
            this.Events.AddHandler(DbServerSyncProvider.EventApplyChangeFailed, value);
            this.Events.RemoveHandler(DbServerSyncProvider.EventApplyChangeFailed, value);

Later in the code they then raise this event with the following untidy bit of code:

protected virtual void OnApplyChangeFailed(ApplyChangeFailedEventArgs value)
      EventHandler<ApplyChangeFailedEventArgs> handler1 = (EventHandler<ApplyChangeFailedEventArgs>) this.Events[DbServerSyncProvider.EventApplyChangeFailed];
      if (handler1 != null)
            handler1(this, value);

This got me thinking about how this would be written in VB – thanks again to reflector I ended up with

        Public Custom Event ApplyChangeFailed As EventHandler(Of ApplyChangeFailedEventArgs)
            AddHandler(ByVal value As EventHandler(Of ApplyChangeFailedEventArgs))
                Me.Events.AddHandler(EventApplyChangeFailed, value)
            End AddHandler
            RemoveHandler(ByVal value As EventHandler(Of ApplyChangeFailedEventArgs))
                Me.Events.RemoveHandler(EventApplyChangeFailed, value)
            End RemoveHandler
            RaiseEvent(ByVal sender As Object, ByVal e As ApplyChangeFailedEventArgs)
                Dim handler1 As EventHandler(Of ApplyChangeFailedEventArgs) = TryCast(Me.Events.Item(EventApplyChangeFailed), EventHandler(Of ApplyChangeFailedEventArgs))
                If (Not handler1 Is Nothing) Then
                    handler1.Invoke(sender, e)
                End If
            End RaiseEvent
        End Event

Ok, so that’s the event declaration – you will notice that most of the code to do with raising the event has now been moved into the RaiseEvent part of the custom event.  Now when we raise the event we just do:

        Protected Overridable Sub OnApplyChangeFailed(ByVal value As ApplyChangeFailedEventArgs)
            RaiseEvent ApplyChangeFailed(Me, value)
        End Sub

I think you would agree this is much tidier from a consumer point of view!