Delegates, Events and the Observer Pattern
14.1 Delegates
Public Delegate Function Validator(Of T)(value As T) As Boolean
Dim notEmpty As Validator(Of String) = Function(s) Not String.IsNullOrWhiteSpace(s)
Dim transform As Func(Of String, String) = AddressOf String.Copy
Dim print As Action(Of String) = AddressOf Console.WriteLine
Dim isPositive As Predicate(Of Integer) = Function(n) n > 0
Dim byLength As Comparison(Of String) = Function(a, b) a.Length.CompareTo(b.Length)
Dim pipeline As Func(Of Integer, Integer) = Function(x) x + 1
pipeline = Function(x) pipeline.Invoke(x) * 2 ' careful: recursion! capture in a local first14.2 Events: Standard Pattern
Public Class OrderPlacedEventArgs
Inherits EventArgs
Public ReadOnly Property OrderId As Integer
Public Sub New(orderId As Integer)
Me.OrderId = orderId
End Sub
End Class
Public Class OrderService
Public Event OrderPlaced As EventHandler(Of OrderPlacedEventArgs)
Protected Overridable Sub OnOrderPlaced(e As OrderPlacedEventArgs)
RaiseEvent OrderPlaced(Me, e) ' RaiseEvent is null-safe
End Sub
Public Sub PlaceOrder(id As Integer)
' ... save ...
OnOrderPlaced(New OrderPlacedEventArgs(id))
End Sub
End Class14.3 Subscribing
' Declarative
Private WithEvents _orders As New OrderService()
Private Sub Orders_Placed(sender As Object, e As OrderPlacedEventArgs) Handles _orders.OrderPlaced
Console.WriteLine($"Order {e.OrderId} placed")
End Sub
' Dynamic
Dim svc As New OrderService()
Dim handler As EventHandler(Of OrderPlacedEventArgs) = Sub(s, e) Console.WriteLine(e.OrderId)
AddHandler svc.OrderPlaced, handler
RemoveHandler svc.OrderPlaced, handler ' avoid leaks: unsubscribe long-lived publishers14.4 Custom Events and Weak Events
Custom Event with AddHandler/RemoveHandler/RaiseEvent blocks for custom storage, thread safety, or WPF CommandManager forwarding.
Weak event patterns (WeakReference, WPF WeakEventManager) prevent publishers from keeping subscribers alive.
Modern alternatives: IObservable(Of T) / Reactive Extensions (System.Reactive), and mediator/message buses (MediatR, WeakReferenceMessenger from CommunityToolkit.Mvvm).