Professional Innovations

September 10th 2014 / C#

Introduction to Delegates in Visual Basic

Posted by Alain Francis

Delegates are objects that you can use to call the methods of other objects. They are described as type-safe function pointers but, unlike in other languages, in VB.NET delegates are reference types based on System.Delegate.

Delegates can reference both functions and subroutines.

Delegates can reference both shared and instance methods.

Delegates can be useful in many scenarios; one is when you have a function that performs different tasks. Since a task can be performed in different ways, you can define a delegate parameter and the caller passes the function that he wants to execute as a parameter. One concrete example is sorting; you can sort a list based on different criteria; for instance, you can sort a list of clients by name, last purchase date, invoices amounts etc… If you write a function for each of those sorting scenarios, you can use delegates to pass it as a parameter to a function that executes it.

Let’s define a delegate for a function that accepts 2 integers and returns a long integer. Notice that when we define a delegate, we care much about its signature and return type. We have not mentioned what the actual mapping functions will actually do; in fact, this is why we create delegates; the above-mentioned delegate can be mapped to a function that sums 2 integers, subtracts 2 integers, multiplies 2 integers etc…

Delegate Function Del1 (ByVal x as integer, ByVal y as integer) As Long

Let’s now define 2 mapping functions:

Function AddIntegers (Byval a as integer, Byval b as integer) As Long
   return a + b;
End Function

Function MultiplyIntegers (Byval a as integer, Byval b as integer) As Long
   return a * b;
End Function

Now, let’s a write a function that makes use of Del1 as one of its parameters:

Function Process (f as Del1, x as integer, y as integer)
   return f(x, y);
End Function

Dim i1 as integer = 5;
Dim i2 as integer = 6;

Dim r = Process(AddressOfAddIntegers, i1, i2);  ‘r = 11

r = Process(AddressOfMultipleIntegers, i1, i2); ‘r = 30

N.B. As previously mentioned, delegates work with both instance and shared methods; however, the delegate itself is not instance nor shared and hence the keyword ‘shared’ cannot be used when defining a delegate; it’s the mapping function(s) that can be instance or shared; we can have 2 implementation functions for the same delegate, the first is shared and the second is instance.

Delegates Rules

 1 – Corresponding parameters between the delegate and the implementations must be the same regarding byval and by ref.

2 – Corresponding types need not to be the same but they need to be convertible (i.e. widening or narrowing). If option strict is on, then widening is allowed only.

3 – If option strict is off, the return types must not be the same but must be convertible through widening or narrowing; if option strict is on, only widening is acceptable.

4 – If the delegate is a function, all implementations must be functions; if the delegate is a subroutine, implementations can be functions, subroutines or both.


Delegates and Lambda Expressions

We can use a lambda expression every time a delegate is expected. Consider the following delegate:

Delegate Sub Del1 (x as integer, y as integer)

Dim d1 As Del1 = Sub (a as integer, b as integer)
MsgBox(a + b);
                               End Sub

Note that the lambda expression must be the same as the delegate; it is a subroutine if the delegate is a subroutine and it is a function if the delegate is a function.