Here is a quick look at the usage of Delegates. Delegates are extremely powerful, but at first glance don't seem all that useful. Anyhow, a Delegate is a type-safe object oriented function pointer.
What's that mean
Well, lets look at the "function pointer" part first. Every function (or subroutine, or whatever) is really only an address in memory. To execute the function, you just move to the address and begin. A delegate object is just a "mobile" container for the memory address. Now the "type-safe" part. In C language there is a Callback method that provides a function pointer. But because the function pointer contains nothing more than the memory address, it does not have the argument list either. This means you can get some nasty results when trying to use a wrong set of arguments. VB.Net's delegate objects are type-safe though, meaning they will error you provide them the wrong set of arguments.
'This is the delegate declaration. Each delegate object must
'have a declaration. The Delegate keyword specifies it as a delegate
Public Delegate Sub delegateDog
Private Sub Example()
'Here we create a delegate object by declaring as
'delegateDog (from the delegate declaration above)
Dim doDog as delegateDog
'set the object to the AddressOf the Size subroutine
doDog = AddressOf Size
'Invoke (or execute) the delegate (which really just executes
'This is the target subroutine that will be used for the delegate
Private Sub Size()
When run, a message box will appear with the words "Big Dog". Nifty. We declared a Delegate subrountine (delegateDog), then created an object as one. We set the delegate object to the AddressOf (returns the type-safe memory pointer) of the Size subroutine. Then we invoked the delegate
The cool thing about delegates is their OO properties. You treat them just like any other objects. They can be passed around from class to class, set to other delegates, etc. Very powerful stuff. Having a hard time seeing what's so great? Here are three examples.
The first is going to go without code, as it would require alot of explanation that is unrelated to delegates. In a typical multithreaded environment, any thread that tries to update the parent thread's UI will have trouble. Things start to get flaky when that happens. Instead of directly accessing the UI, or passing a reference to the form, you can pass a delegate. The delegate is set to the UI update function, then passed as an argument to the new thread. The thread can then update the UI whenever it chooses. Why can it do this? Because it's accessing the parent thread's function (and thus in the thread space of the parent), to update the UI (which is perfectly fine).
This is also codeless, because it is more of an explanation. Delegates can be used to give access to any function from any class. Say I have a private function in mySuperClass. I can create a delegate of that function and pass it to myClass. Normally, even if a reference of the class was passed, that function could not be accessed. But because you have a delegate of the fucntion, you can execute it from myClass (despite not having adequate "permission" to do so).
Last example, and this one has code. Ever wonder how Events work? An event just uses Delegates! VB.Net hides some stuff from you to make the interface nicer, but it's the same thing. Let's make a simple app that sets your bank balance (with a slider) and displays your "wealth rating".
First, the bank class:
Public Class clsBank
'An enum for making our lives easier
Public Enum eWealth
'the delegate declaration, this time it has an argument that may
'be passed as well. The argument is an eWealth Enum
Public Delegate Sub BankEventHandler(ByVal WealthRating As eWealth)
'Now we declare the actual delegate object
Private doWealthRating as BankEventHandler
'A variable to hold the actual wealth value
Private intWealth as Int32
'This function allows the calling class to pass the delegate in initially.
'The delegate object will be passed to us from the calling class so that
'we can manipulate it
Public Sub PassDelegate(ByVal doDel as BankEventHandler)
doWealthRating = doDel
'Property that we will be using to show how events are the same as events
Public Property WealthRating() As Int32
'If the value set is less than zero, set it to zero
Set(ByVal Value As Int32)
If Value < 0 Then
intWealth = 0
'Otherwise, set the internal wealth variable to the passed value
intWealth = Value
' And here set up a select case on the value
'Each different case we invoke the delegate object and pass
'one of the Enum values. This is essentially executing the subroutine
'in the calling class.
Select Case intWealth
Case is > 100
Case 60 To 99
Case 30 To 59
Case 1 To 29
Case is = 0
We have alot going on in this code. First we have an Enum to make our lives easier later on. Then we have the declaration of the delegate subroutine, and then the actual object for the delegate. There is a subroutine to pass in the delegate from the calling class, and a property for the wealth rating.
And now the class to use the previous code:
Public Class Form1
'A new instance of the bank class from the previous code
Private oWealth as New clsBank
'On the form load, we want to pass the AddressOf (the type
'safe function pointer) to the new class instance. This is so
'the bank class can manipulate the delegate object.
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Scrollbar event. Here we use the public property of the bank
'to set the value.
Private Sub scrBankWealth_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles trInkLevel.Scroll
oWealth.WealthRating = scrBankWealth.Value
'At the same time the scroller is moved, the delegate object in the other
'class will invoke this method (much like an event). It will also pass a
Private Sub WealthStatus(ByVal Status as clsBank.BankEventHandler)
Dim Value as String
'A select case to display the value in a label
Select Case Status
Value = "FilthyRich"
Value = "Rich"
Value = "Modest"
Value = "Poor"
Value = "LiveInBox"
lblStatus = State
Here, we have a new instance of the clsBank Class. On the load of the form, we pass a delegate to the class using AddressOf. Then there is the slider control's subroutine, which updates the class' wealth value. Then there is our delegate subroutine, WealthStatus, which displays the status in a label.
As you slide the slider, the label will change accordingly. Go back and look at the WealthRating property in clsBank. Notice how when it is set, it will invoke the delegate and pass an argument. Looking back at Form1, we see the delegate subroutine accepts the argument and deals with it by a select case and a label output.
Essentially, we just created a custom programmable Event and Event Handler. Pretty cool.
Delegate objects are extremely powerful, allowing you to access functions from anywhere in an object oriented manner. They can also be used to create custom events.