How to Use the Action and Predicate DelegatesR. Lee Ermey’s VB.NET Boot Camp

Introduction To VB.NET Delegates

August 24th, 2007

I read that using delegates will make you even more productiveIn 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.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

Entry Filed under: VB.NET Tutorials


Rate This Article:

Not That GoodCould Be BetterOKGoodGreat (9 votes, average: 3.56 out of 5)
Loading ... Loading ...

6 Comments Add your own

  • 1. Awais  |  October 4th, 2007 at 12:36 am

    Your article is great. It helped me very much in understanding of Delegates. Carry on. Take care.

  • 2. jfrankcarr  |  October 4th, 2007 at 7:52 am

    Thanks Awais

    I’m glad you found it helpful.

  • 3. David  |  June 3rd, 2008 at 12:53 pm

    Hi,
    Indeed, very usefull article. It helped me better to understand the use of delegates. However, there is one thing that doesn’t seem to work for me. I can give my delegates access to any function or procedure within another class as long as the delegate function as well as the target function are declared as public shared, not as private and the delegate is declared outside a custom class.
    probably i’m looking over something here but i can’t figured it out.

    My target functions are within normal class (class.vb) and the delegate routine stands above this class but in the same file.
    I invoke the delegate in a partial class on a code behind file (.aspx) and it works when as well delegate and routine are declared as public (shared).

    Thanks

  • 4. ramnani shaila  |  November 26th, 2008 at 4:09 pm

    i don’t have a comment thanks for all this ..just have a few more question regarding delegates if u can help me out… how properties and attibutes of an object can be set?
    try to ans me if u can thanks

  • 5. Tariq  |  July 14th, 2009 at 5:24 am

    Simply, Best explaination found
    Thanks a lot

  • 6. John Wood  |  October 9th, 2009 at 12:27 pm

    hey jfrankcarr,
    Could you check this out and see what you think the hell someone was thinking when they did this?

    CustomConverters.Add(typeof(Color), delegate(object value) { return ColorTranslator.ToHtml((Color) value); });
    Converter dateTimeConverter = delegate(object value)
    {
    DateTime? date = (DateTime?) value;
    return (date != null) ? date.Value.ToUniversalTime().ToString("r") : null;
    };
    CustomConverters.Add(typeof(DateTime), dateTimeConverter);
    CustomConverters.Add(typeof(DateTime?), dateTimeConverter);

Leave a Comment

Required

Required, hidden

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed


Visit Me At My New Site, Programming In C#

Most Popular Articles

Highest Rated Articles

Categories

Most Recent Articles

Feeds

 Subscribe in a reader

To subscribe by e-mail
Enter your address here

Delivered by FeedBurner

VB Opportunities

Archives