August 24th, 2007
In my previous article, How to Use the Action and Predicate Delegates, I touched on the subject of delegates. MikeP sent me an email asking me to cover a little more general information about delegates and how to use them so I put together this article.
What is a Delegate
Essentially a delegate is a function pointer, the memory address of where a routine’s code starts in memory. If we were programming in a low level language like C/C++ we would be working with these memory positions directly. If the programmer gets these pointers wrong a crash is a common result. Fortunately for us, .NET shields us from this often dangerous complexity by encapsulating the memory address of functions in the type-safe, object oriented, delegates. The .NET Framework uses delegates a lot behind the scenes when you call a routine or an event is fired. In this article we will look at some ways to use delegates in your own code.
A Simple Delegate Example
To begin with, a Delegate is declared like this:
Private Delegate Sub WriteToDisk() ....... Private Delegate Function UpdateFile(ByVal fileName As String) As Boolean
In this example we have two delegates, one is a sub with no parameters and the second is a function with one parameter. Now we can write our actual routines. Note that the routines we plan to use with the delegate that matches the signature of the delegate. Here are two example prototype routines for our delegates above:
Private Sub WriteUserFile() 'code to write user file data goes here End Sub Private Function UpdateUserAddress(ByVal userFileName As String) As Boolean 'code to update address field goes here End Function
Now, use the delegate, we would use the following code:
Dim DoUpdate As UpdateFile DoUpdate = New UpdateFile(AddressOf UpdateUserAddress) DoUpdate.Invoke(CurrentUserFileName)
These lines would create a new delegate, set the pointer to the address of the appropriate routine and then invoke it.
When and Where To Use a Delegate
Of course, our example above is a little silly. After all, why don’t you just call the desired routine directly? In ‘real world’ coding you should only use delegates when you don’t know the function you’re going to call until the program is running. You don’t want to have the extra overhead and increase the complexity of your code by using them without a reason. So when would you use them?
One delegate trick is to use them to give access to any function from any class. For example, if you had a private function in a class, you could create a delegate of that function and pass it to another class. Under normal conditions, even if you passed in a reference to the class, the private function could not be accessed. However, by using a delegate, it can be executed. It might look something like this:
Dim DoUpdate As UpdateFile = New UpdateFile(AddressOf UpdateUserAddress) Dim UpdateRunner As New Updater(DoUpdate)
Where “UpdateUserAddress” is a private function that’s passed to another class as a delegate.
You can even make this quite generic by using a Delegate parameter, like so:
Function UpdateAdditionalFields(ByVal routineToCall As [Delegate]) As Boolean routineToCall.DynamicInvoke(MyLocalData) End Function
This is kind of risky and has some significant conversion overhead but if you need a lot of flexibility, this is a way to get it. Notice that here we use the DynamicInvoke method rather than Invoke since we don’t know exactly what we will be working with until runtime. Some additional type checking would also be in order here as well.
Another common usage of delegates is in using delegates to update a form’s user interface when threading. As you may know, you can’t update a form’s UI from a background worker thread. So, instead, you pass a delegate function to the background that can update the UI as needed. Since the delegate is actually operating in the parent’s UI thread it can do the updates without a problem.
One other way you’ll see delegates used is with Events. VB.NET already does a lot of stuff behind the scenes this way. You can leverage this to create custom events. Another is the Action, Predicate and other such methods that I mentioned in my previous article.
Multicast For More Power
A powerful feature of delegates is that you aren’t limited to pointing to just one function. The System.Delegate type has an Invocation List that holds references to the functions to be called by the delegate. This allows you to mix and match your delegate calls as needed. For our example here, let’s assume we have three functions that need to be called to update an object. Here’s how you would combine them into a delegate:
Dim Addr As New UpdateUserInfo(AddressOf UpdateAddress) Dim Phone As New UpdateUserInfo(AddressOf UpdatePhone) Dim Email As New UpdateUserInfo(AddressOf UpdateEmail) Dim Updates As UpdateUserInfo = DirectCast([Delegate].Combine(Addr, Phone, Email), UpdateUserInfo) Updates.Invoke(CurrentUser)
You can also add additional delegates to the list or remove existing ones as shown here:
Dim UserName As New UpdateUserInfo(AddressOf UpdateName) Updates = DirectCast([Delegate].Combine(Updates, UserName), UpdateUserInfo) ......... Updates = DirectCast([Delegate].Remove(Updates, UserName), UpdateUserInfo)
As you can imagine, using this technique can be very powerful when you want to dynamically call routines. Note that the delegates are executed synchronously in the order they were added to the list. Also, should one of the methods called encounter an exception, then the delegate operation stops at that point.
I hope this gives you some ideas on how to use Delegates in your programs. If you would like for me to get into more detail about some of the ways to use delegates in a future article or have your own ideas about how to use them, please leave a comment or send me an email.
Entry Filed under: VB.NET Tutorials
Rate This Article: