Developing with . NET Delegates

By Ramesh Balaji

Introduction

Of the many new capabilities provided by .NET through its Common Language Runtime and .NET framework classes, "Delegates" or .NET Delegates is one worth examining.

This article covers the following aspects of Delegates.

a. Defining Delegates.

b. Using Delegates

c. Understanding how Delegate functions in the CLR Environment.

I am going to use VB.NET (BETA 2) to run through my examples.

Defining Delegates

Delegate is commonly defined as a Type Safe Pointer. To better understand a Type-Safe pointer, let's see a how a callback function in C++/VC++ works. The Callback function is normally implemented in the Business tier of a 3-tier architecture (of course there are exceptions to that). Once the Business Logic component implements a particular functionality, say a complex arithmetic calculation, it informs a client that the job was performed successfully. In order to inform the client, it needs an address of the function\method implemented in the client. The address of a function is just a memory address; this address does not carry any information such as number of parameters, data type of each parameter and its return value. Since the Callback function does not have any idea of the Method Signature it is going to call, in short, it is not Type Safe.

However, Delegates provide the feature of Callback functions in a safe way. Taking the previous example, if the Business Logic finds that the function signature implemented by the Client differs in terms of number of parameters or parameter types or return values as opposed to the method signature, it is going to safely raise an error.

Using Delegates

We can better understand through an example.

As a owner of a fictitious toy firm trying attract more local customers, I am going to offer special discounts of 10% on all toys to all local residents, whom I will identify by their phone numbers. If their area code is "479" (which is my area code), I am going to raise a message to the client saying "The Customer is eligible for 10% Discount"

This is a Normal Windows Form App written in VB.NET, which is going to accept the Customer First Name, Last Name and the Phone Number, which includes the area code and will perform the validation.

Step 1, I am going to define a Delegate called "MakeDelegate". The code below is fundamental syntax for declaring a Delegate in VB.NET


	Public Delegate Sub MakeDelegate (ByVal PhoneNo As String)

This Delegate class "MakeDelegate" is now capable of invoking a function, which can accept a Single String Parameter and will return VOID.

Being a Public type, it can be called anywhere inside my Application.

Step 2,

I am going to define a Customer Class, which has the following fields and a method.


Public Class Customer
    Public FirstName As String
    Public LastName As String

    Public Sub ValidateCustomer (ByVal objDelegate As MakeDelegate, _
                                ByVal PhoneNo As String)
        If PhoneNo.StartsWith ("479") Then
            objDelegate.Invoke(PhoneNo)
        End If
    End Sub

End Class

The method ValidateCustomer is going to accept the PhoneNo and a Delegate Object of type "MakeDelegate" as the parameters and validate whether it is a local code or long-distance code and invoke the Delegate Object accordingly.

The Fields FirstName and LastName will store the customers' first and last names.

In the third step, we are going to tell the Delegate object which Function/Procedure at the form class needs to be called when "ObjDelegate.Invoke(PhoneNo)" is called.


        Dim objCustomer As Customer = New Customer()

        Dim objDelegate As MakeDelegate
        objDelegate = AddressOf NotifyClient

        objCustomer.FirstName = txtFirstName.Text
        objCustomer.LastName = txtLastName.Text

        objCustomer.ValidateCustomer(objDelegate, txtPhoneNo.Text)


If we have a look at the above code, Customer Class instance is created and the reference variable for the "MakeDelegate" Delegate object is assigned.

Now examine the following line


objDelegate = AddressOf NotifyClient

We assign the local procedure "NotifyClient", which is declared and defined inside the Windows Form Class to the Delegate Object.
  
 Private Sub NotifyClient(ByVal PhoneNo As String)
        MsgBox("This Customer is Eligible for 10% Discount")
End Sub

Once we assign the instance of the Delegate, we must provide the address of a method implementation with a matching method signature.

If we carefully take a look at the NotifyClient, it also has a Single Parameter of data type String and it returns Void. The signature of "NotifyClient" procedure matches the signature of the Delegate "MakeDelegate".

Assume that if MakeDelegate declaration looks like the declaration below


Public Delegate Sub MakeDelegate(ByVal PhoneNo As String, byval SomeValue as long)

then I am going to get a Compile time error. This is what we call Type Safe function pointers. If we look at the way .NET implements delegates, it always sees the matching signature starting with the function parameters, their data types, and the return values.

In a summary, If I run this program, the Customer class will be instantiated along with the delegate object "MakeDelegate", the Address of local form class procedure NotifyClient is assigned to the Delegate class.

The ValidateCustomer Method of the Customer Class is called and it checks the PhoneNo. When it finds the phone number starts with "479", it is going to call the Invoke method of the MakeDelegate object which will eventually call the "NotifyClient" function.

Understanding Delegates

The implementation of Delegates is not really complicated because CLR and VB.NET compiler does a lot of things behind the scenes.

Let's re-examine the following code


Public delegate MakeDelegate(phoneno)

When the VB.NET compiler sees the above line, it creates a public class "MakeDelegate" because it is declared as Public Delegate. If it would have been declared as Private, then it is going to create a Private class. This class will inherit from System.MultiCastDelegate. Which means all properties and methods of System.MulticastDelegate class will be inherited to the "MakeDelegate" Delegate Class

__[CLS] MakeDelegate
   |   |   |     .class public auto ansi sealed 
   |   |   |      extends [mscorlib]System.MulticastDelegate 
   |   |   |___[MET] method .ctor : void(object,native int)

   |   |   |___[MET] method BeginInvoke : class [mscorlib]System.IAsyncResult(string,class 
[mscorlib]System.AsyncCallback,object)
   |   |   |___[MET] method EndInvoke : void(string,class [mscorlib]System.IAsyncResult)
   |   |   |___[MET] method Invoke : void(string)
   |   |

I also pasted the ILDASM code above for further clarification.

When you take a look at the Delegate Constructor (bolded) in the ILDASM code, there are two parameters. The first parameter indicates the reference of the object being passed and the second parameter is the int32 value that identifies the Method. From our example, it should have "objCustomer" as the value for object reference parameter and "NotifyClient" as the value in the MethodInfo parameter.

The reference to object and method value is saved on the private fields respectively. In case you pass the Static Object, the object reference is set to NULL.

Now that we understand how the Delegate constructs objects, let's see how the method is actually invoked.

I've pasted the line from ILDASM, that calls the invoke method of the Delegate Class.


 	|___[MET] method Invoke : void(string)

Look at it carefully. The compiler actually generates code to call the delegate object invoke method whenever it sees this line of code

objDelegate.Invoke(PhoneNo)

This is how the .NET Delegate class works internally. However, it performs lots of things internally when it needs to invoke a chain of Delegate objects and during Asynchronous calls, but they are beyond the scope of this article.

Conclusion

In summary we now understand:

a. What is a Delegate and its purpose.

b. How to implement Delegates.

c. How a Delegate works

What I have given is just an introduction. If you would like to delve deeper into Delegate Classes, there are lot of useful articles you can find in http://msdn.microsoft.com (search for .NET Delegates). Happy reading!

About the Author

Ramesh Balaji develops business applications using ASP, VB and SQL Server. He's a frequent contributor to the www.4guysfromrolla.com and www.asptoday.com. When not programming, he enjoys spending time with his kids. He can be reached at iambramesh@yahoo.com.



Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • With the average hard drive now averaging one terabyte in size, the fallout from the explosion of user-created data has become an overwhelming volume of potential evidence that law-enforcement and corporate investigators spend countless hours examining. Join Us and SANS' Rob Lee for our 45-minute webinar, A Triage and Collection Strategy for Time-Sensitive Investigations, will demonstrate how to: Identify the folders and files that often contain key insights Reduce the time spent sifting through content by …

Most Popular Programming Stories

More for Developers

RSS Feeds