Sunday, April 17, 2005 - Posts

Event handler declarations

This is a bit of old news, but seeing as I just stumbled on it again, I thought it made sense to blog it.

When declaring an event, it’s best practice to create and/or define the type of that event, instead of allowing implicit creation. So, for example, if you declare an event as:

Public Event SomePropertyChanged

And don’t define the type, then the vb.net compile will do this for you. You end up with a new class being created for you (if you examine the IL you can see this). The class will be called SomePropertyChangedEventHandler and it extends (inherits from) System.MulticastDelegate. A field is then declared called SomePropertyChangedEvent, which holds the invocation list of subscribers to your event.

One of the reason why this is not considered best practice is because for every event declared, you will essentially be creating a new class. If you have a project with a fair amount of events, you will be creating an additional class for each of these. Additionally, you have no defined signature arguments for the event.

So, for the following code:

Public Class Class1

     Public Event ColorPropertyChanged()

     Public Event HeightPropertyChanged()

     Public Event WidthPropertyChanged()

     Public Event TransparencyPropertyChanged()

     Public Sub DoSomething()

          RaiseEvent ColorPropertyChanged()

          RaiseEvent HeightPropertyChanged()

          RaiseEvent WidthPropertyChanged()

          RaiseEvent TransparencyPropertyChanged()

     End Sub

End Class

You will end up with IL that looks like this:
EventHandler1

Notice that besides for the 4 event declarations, we also have 4 class declarations; 1 new class created for each event declaration.

If you instead define the type of your event, such as:


Public Event As EventHandler


The .Net compile won’t need to implicitly create a class to handle your events because you’ve declared your event as a predefined class type; in this case System.EventHandler (which is a delegate type used to wrap System.MulticastDelegate.)

So, if you instead declare the events as such:

Public Class Class1

     Public Event ColorPropertyChanged As EventHandler

     Public Event HeightPropertyChanged As EventHandler

     Public Event WidthPropertyChanged As EventHandler

     Public Event TransparencyPropertyChanged As EventHandler

     Public Sub DoSomething()

          RaiseEvent ColorPropertyChanged(Me, New EventArgs())

          RaiseEvent HeightPropertyChanged(Me, New EventArgs())

          RaiseEvent WidthPropertyChanged(Me, New EventArgs())

          RaiseEvent TransparencyPropertyChanged(Me, New EventArgs())

     End Sub

End Class

You will be creating IL that looks like this:
EventHandler2

Notice that in this sample, there is not a separate class created for each Event type. Instead, all of the event declarations are of type System.Event, which is a system defined Delegate that extends System.MulticastDelegate.

If you need to provide a different signature and arguments from System.EventHandler, then you can define your own type delegate. For example:

Public Class Class1

     Delegate Sub MyPropertyChangedEventHandler(ByVal sender As Object, ByVal e As MyEventArgs)

     Public Event ColorPropertyChanged As MyPropertyChangedEventHandler

     Public Event HeightPropertyChanged As MyPropertyChangedEventHandler

     Public Event WidthPropertyChanged As MyPropertyChangedEventHandler

     Public Event TransparencyPropertyChanged As MyPropertyChangedEventHandler

     Public Sub DoSomething()

          RaiseEvent ColorPropertyChanged(Me, New MyEventArgs())

          RaiseEvent HeightPropertyChanged(Me, New MyEventArgs())

          RaiseEvent WidthPropertyChanged(Me, New MyEventArgs())

          RaiseEvent TransparencyPropertyChanged(Me, New MyEventArgs())

     End Sub

End Class

This allows .Net to create one type that each event field can be declared as. When this code is compiled, the IL looks like this:
EventHandler3

Notice in this IL, there is a single Class defined for the MyPropertyChangedEvnetHandler delegate, and then each respective Event is defined as this type.

So, by defining the type of your Event declaration, you control the number of instances of new event handler classes created. This is better practice then allowing .Net to implicitly create new event handler classes for each and every event declaration; especially if you have a large number of events declared. Additionally, by defining your own event delegate handler, you are able to control and define the signature of the event.