Declaring Events in Classes, Structures, and Interfaces

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
					

TIP

Events cannot define a return type. That is, events must always have subroutine-style signatures.


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

TIP

By convention we use a method to raise events rather than littering our types with RaiseEvent statements.


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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.100.40