Delegates VB.NET

In a never-ending effort to deny VB programmers the right to use pointers, Microsoft has implemented a feature called delegates that, according to the documentation, provide a safe alternative to function pointers.

As you may know, a pointer variable (or pointer) is simply a variable whose value is interpreted by the compiler as a memory address. The address to which the pointer points is the target of the pointer, and we say that the pointer variable points to that target address. If the target address is a variable of data type Integer, for example, then we say that the pointer is of type Integer or is an Integer pointer. Thus, the type of a pointer is the type of the target variable. (We have seen that, as reference types, variables of type Object and String are both pointers; i.e., their values point to the address of the data in memory.)

A pointer can also point to a function, that is, contain the address of a function. Even though a function is not a variable, it does have a physical location in memory and so can be the target of a pointer. (Actually, it's reasonable to think of a function as a type of variable, but that is another story.) In this case, we have a function pointer.

Function pointers are very useful in certain situations for calling or specifying functions. This is commonly done in the C++ programming language, where function pointers are supported directly.

One area in which function pointers are used is in the context of callback functions. To illustrate, if we want to enumerate all of the fonts on a given system, the Windows API provides a function called EnumFontFamiliesEx, defined as follows:

The third parameter requires the address of a function we must declare, called a callback function. The reason for this term is that Windows will call our callback function for each font in the system, passing information about the font in the parameters of the function. According to the documentation, the callback function must have a particular form:

The point here is that to use EnumFontFamiliesEx, we need to pass the address of a function as one of the parameters.

As you may know, this is done in VB using the AddressOf operator. In earlier versions of VB, this operator is described as follows:

A unary operator that causes the address of the procedure it precedes to be passed to an API procedure that expects a function pointer at that position in the argument list.

Put another way, the AddressOf operator is implemented in VB 6 for the express purpose of passing function addresses to API functions.

In VB .NET, the AddressOf operator returns a delegate, which is, as the documentation states:

A unary operator that creates a procedure delegate instance that references the specific procedure.

So let us discuss delegates. We begin with a rather unhelpful definition: a delegate is an object of a class derived from either the Delegate class or the MulticastDelegate class. These two classes are abstract, so no objects of these classes can be created. Nevertheless, other classes can be derived from these classes, and objects can be created from these derived classes.

In VB .NET, delegates can be used to call methods of objects or to supply callback functions. In addition, VB .NET uses delegates to bind event handlers to events. Fortunately, VB .NET also supplies tools (such as the AddHandler method) to automate this process, so we don't need to use delegates directly for this purpose.

A delegate object inherits a number of properties and methods from the Delegate or MulticastDelegate class. In particular, a delegate object has:

  • A Target property that references the object or objects whose method or methods are to becalled.
  • A Method property that returns a MethodInfo object that describes the method or methods associated with the delegate.
  • An Invoke method that invokes the target method or methods.

By now you have probably guessed that there are two delegate classes because delegates derived from the Delegate class can only call a single method, whereas delegates derived from MulticastDelegate can call multiple methods.

Using a Delegate to Call a Method

To call a method using a delegate, we call the Invoke method of the delegate. To illustrate, consider the class module with a simple method:

Now, in a module with a Windows Form (referred to as a form module in earlier versions of VB), we declare a (single cast) delegate with the same parameters as the target method we wish to call:

Delegate Sub ADelegate(ByVal s As String)

The following code then uses the delegate to call the AMethod of Class1:

Note that the documentation describes the delegate constructor as taking two parameters, as in:

However, Visual Basic is not capable of handling the second parameter, so VB supports the special syntax:

We point this out only to warn you about the documentation on the delegate class constructor.

Using a Delegate as a Function Pointer

The following example illustrates the use of a delegate in the context of a callback function. In this example, we want to create a generic sort function for sorting integer arrays. The function uses the bubble sort algorithm for sorting, but it's generic in the sense that one of its parameters is a compare function that is used to do the comparison of adjacent integers. Thus, by varying the external comparison function, we can change the type of sorting (ascending, descending, or some other method) without changing the main sort function. The compare function is a callback function, since it is a function we supply that is called by the main sort function. (In this case, the callback function is not supplying us with information, as in the font enumeration case described earlier. Instead, it is called to help the sort function do its sorting.)

First, we declare a delegate. As part of the declaration of a delegate, we must specify the signature of the method that is associated with the delegate, which, in our case, is the compare function. Since the compare function should take two (adjacent) integers and return True if and only if we need to swap the integers in the bubble sort algorithm, we declare the delegate as follows:

Here are two alternative target methods for the delegate—one for an ascending sort and one for a descending sort:

Now we can define the sort routine. Note the call to the Invoke method of the delegate:

Here is some code to exercise this example:

The output is, as you would expect:

All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd Protection Status

VB.NET Topics