Delegates and Events in Visual Basic

Delegates and events are fundamental concepts in object-oriented programming, particularly in event-driven applications like those built with Visual Basic. They provide a powerful mechanism for implementing the publish-subscribe pattern, allowing objects to communicate with each other without direct coupling.

Understanding Delegates

A delegate in Visual Basic is a type that represents references to methods with a particular parameter list and return type. Think of it as a type-safe function pointer. Delegates are declared using the Delegate keyword.

Delegate Declaration

The syntax for declaring a delegate is as follows:


Delegate Sub MyDelegate(ByVal message As String)
' Or for a function:
' Delegate Function Calculate(ByVal a As Integer, ByVal b As Integer) As Integer
            

This declares a delegate named MyDelegate that can point to any method that takes a single String argument and returns Sub (void).

Instantiating and Using Delegates

Once a delegate type is declared, you can create instances of it and assign methods to them. The methods assigned must match the signature of the delegate.


' Assume MyMethod1 and MyMethod2 have the correct signature
Public Class MyClass
    ' Declare a delegate instance
    Public WithEvents Handler As MyDelegate

    Public Sub New()
        ' Assign a method to the delegate
        AddHandler Handler, AddressOf MyMethod1
        ' Or directly: Handler = New MyDelegate(AddressOf MyMethod1)
    End Sub

    ' A method that matches the delegate signature
    Private Sub MyMethod1(ByVal message As String)
        Console.WriteLine($"Method 1 received: {message}")
    End Sub

    Private Sub MyMethod2(ByVal message As String)
        Console.WriteLine($"Method 2 received: {message}")
    End Sub

    Public Sub TriggerEvent(ByVal text As String)
        ' Invoke the delegate (which invokes the assigned methods)
        If Handler IsNot Nothing Then
            Handler(text)
        End If
    End Sub
End Class
            

Understanding Events

An event is a mechanism by which a class (the publisher) can notify other classes (the subscribers) when something significant happens. Events are built upon delegates. A class that raises an event declares a delegate and then declares an event using that delegate type.

Event Declaration

The Event keyword is used to declare an event. It is typically declared as Public to allow other objects to subscribe to it.


Public Class Publisher
    ' Declare the delegate for the event
    Public Delegate Sub DataChangedEventHandler(ByVal sender As Object, ByVal e As EventArgs)

    ' Declare the event using the delegate
    Public Event DataChanged As DataChangedEventHandler
    ' Alternative using a generic event handler:
    ' Public Event DataChanged As EventHandler(Of EventArgs)

    Private _data As String
    Public Property Data() As String
        Get
            Return _data
        End Get
        Set(Value As String)
            If _data <> Value Then
                _data = Value
                ' Raise the event when data changes
                OnDataChanged(EventArgs.Empty)
            End If
        End Set
    End Property

    Protected Overridable Sub OnDataChanged(ByVal e As EventArgs)
        ' Check if there are any subscribers before raising the event
        RaiseEvent DataChanged(Me, e)
    End Sub
End Class
            

Subscribing to an Event

Other classes can subscribe to an event using the AddHandler statement. The method that handles the event must match the delegate's signature.


Public Class Subscriber
    Public Sub New(ByVal publisher As Publisher)
        ' Subscribe to the DataChanged event
        AddHandler publisher.DataChanged, AddressOf Me.HandleDataChange
    End Sub

    ' Event handler method
    Private Sub HandleDataChange(ByVal sender As Object, ByVal e As EventArgs)
        Console.WriteLine("Data has changed!")
        ' You can also cast sender to Publisher to access its properties
        Dim pub As Publisher = CType(sender, Publisher)
        Console.WriteLine($"New data: {pub.Data}")
    End Sub

    ' To unsubscribe:
    ' RemoveHandler publisher.DataChanged, AddressOf Me.HandleDataChange
End Class
            

Key Concepts and Best Practices

Note on Generics:

Starting with .NET Framework 3.5, you can use the generic EventHandler(Of TEventArgs) delegate, which often simplifies event declarations and usage, especially when custom data needs to be passed.


' Declaration
Public Event MyCustomEvent As EventHandler(Of MyCustomEventArgs)

' Raising
Protected Overridable Sub OnMyCustomEvent(ByVal e As MyCustomEventArgs)
    RaiseEvent MyCustomEvent(Me, e)
End Sub

' Handler
Private Sub HandleMyCustomEvent(sender As Object, e As MyCustomEventArgs)
    ' Access e.CustomProperty
End Sub
                

By mastering delegates and events, you can build more robust, scalable, and responsive applications in Visual Basic.