We have examined a variety of ways to use events as consumers. Now we need to explore how to use events as producers . This section demonstrates how to declare event members for classes, structures, and interfaces. Keep in mind, though, that the event grammar is the same regardless of which type the event is defined in.
There are two basic signatures for events, as shown below.
Modifiers Event signature Modifiers Event Name As delegate
The first example above defines an event by signature. An event includes the name of the event and the arguments for name, type, and number. The second example above defines an event as a delegate, and the delegate provides the signature of the event. Here is an example of an event that uses an existing delegate, EventHandler .
Public Class Event1 Public Event Handle As EventHandler Public Sub Raise() RaiseEvent Handle(Me, System.EventArgs.Empty) End Sub End Class
The fragment defines a class that has a public access modifier and is defined as an event handler. EventHandler is the delegate used for events like Click . The Raise method demonstrates how to use RaiseEvent . This code works correctly whether any event handler is defined or not. Me satisfies the sender argument, and the shared System.EventArgs.Empty object satisfies the EventArgs argument of EventHandler . (To review how to create instances of objects and how to associate event handlers with the events of those objects, refer to two earlier sections in this chapter: Using the WithEvents Statement and The AddHandler Statement.)
If you replace Class with Interface or Structure in the fragment containing the definition of the Event1 type, the event handler definition will remain the same. But remember that declarations within an interface can't use access modifiers (so remove the keyword Public on the Raise method), and we can't implement any code (so remove Raise 's method body). The following two examples demonstrate the differences between implementing the interface and the structure.
Public Interface IEvent1 Event Handle As EventHandler Sub Raise() End Interface Public Structure Event1 Public Event Handle As EventHandler Public Sub Raise() RaiseEvent Handle(Me, System.EventArgs.Empty) End Sub End Structure
To implement the same event using a method signature we need to replace the As clause with the method signature. The revision to the event definition follows .
Event Handle(ByVal sender As Object, ByVal e As System.EventArgs)
You must use methods whose signatures match the event signature whether that signature is expressed literally or as defined by a delegate.
More important than the syntax is the motivation for using events. If you reexamine the Event1 class (or the interface or structure) you will notice that there is no indication of the objects that will be handling the Handle event. This is critical. Because we do not have a reference to a specific object and aren't invoking a specific method, any object that has a method with a matching signature can handle the event raised by Event1 . This is the essence of loose coupling, and loosely coupled code is our goal.