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:

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:

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:
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.