Wednesday 11 January 2012

Delegates and Events

Delegates and Events
Delegates:-
   The Delegate class is one of the most important classes to know how to use when programming .NET. Delegates are often described as the 'backbone of the event model' in VB.NET. In this we are going to introduce you to delegates (Sytem.Delegate class) and show you how powerful of an event mechanism
through delegates.
  Delegates are implemented using the delegate class found in the System namespace. A delegate is nothing more than a class that derives from System.MulticastDelegate. A delegate is defined as a data structure that refers to a static method or to a class instance and an instance method of that class. In other words, a delegate can be used like a type safe pointer. You can use a delegate to point to a method, much like a callback or the 'AddressOf' operator in VB.NET. Delegates are often used for asynchronous programming and are the ideal method for generically defining events.
    Before you get into the actual delegate class let us see some code which simulates the delegate functionality through simple class code for the sake of understanding. We have a simple class called 'VBDelegate' with two static methods named 'CallDelegate' and 'DisplayMessage' as shown below. When the CallDelegate method is called,(when the program is run) to display the message. Now normally, if we had a class called 'VBDelegate' with a method named 'DisplayMessage'

VB.NET
Public Class VBDelegate
'Static method to call displaymessage function
Public Shared Sub CallDelegate()
DisplayMessage("Some Text")
End Sub
'Static Function to display the message
Private Shared Function DisplayMessage(ByVal strTextOutput As String)
MsgBox(strTextOutput)
End Function
End Class

C#
Public Class CSDelegate
{
'Static method to call displaymessage function
Public static void CallDelegate()
{
DisplayMessage("Some Text")
}
'Static Function to display the message
Private static void DisplayMessage(String strTextOutput)
{
MessageBox.Show(strTextOutput)
}
}
  There is nothing wrong with this approach at all. In fact, it is probably more commonly used than delegates. However, it does not provide much in terms of flexibility or a dynamic event model. With delegates, you can pass a method along to something else, and let it execute the method instead. Perhaps you do not know which method you want to call until runtime, in which case, delegates also come in handy.
   Now we will implement the same functionality as before, using a actual delegate class of .NET.
Delegates in VB.NET are declared like:
Delegate [Function/Sub] methodname(arg1,arg2..argN)
  The declared delegate methodname will have the same method signature as the methods they want to be a delegate for. This example is calling a shared method..

VB.NET
Class VBDelegate
'Declaration of delegate variable with arguments
Delegate Function MyDelegate(ByVal strOutput As String)
'Function to call the delegates
Public Shared Sub CallDelegates()
'Declare variables of type Mydelegate points to the
'function MessageDisplay with AddressOf operator
Dim d1 As New MyDelegate(AddressOf MesssageDisplay)
Dim d2 As New MyDelegate(AddressOf MesssageDisplay)
'Pass the arguments to the function through delegates
d1("First Delegation ")
d2("Second Delegation ")
End Sub
'Function to display the message
Private Shared Function MesssageDisplay(ByVal strTextOutput As String)
MsgBox(strTextOutput)
End Function
End Class


C#
Class CSDelegate
{
'Declaration of delegate variable with arguments
delegate void MyDelegate(String strOutput);
'Function to call the delegates
Public static void CallDelegates()
{
'Declare variables of type Mydelegate points to the
'function MessageDisplay
MyDelegate d1 = New MyDelegate(MesssageDisplay);
MyDelegate d2 = New MyDelegate(MesssageDisplay);
'Pass the arguments to the function through delegates
d1("First Delegation ");
d2("Second Delegation ");
}
'Function to display the message
Private static void MesssageDisplay(String strTextOutput)
{
MessgeBox.Show(strTextOutput);
}
}
The Output to the display window is:
First Delegation in one message window
And
Second Delegation in the second message window
What has happened in the above code? Let's take a look
  First, we defined a delegate. Remember, when defining a delegate it is very similar to stating the signature of a method. We have said we want a delegate that can accept a string as an argument so basically, this delegate can work with any method that takes the same argument(s).
   In our CallDelagates method, we create two instances of our 'MyDelegate'. Then, we pass into MyDelegate's constructor the address of our 'DisplayMessage' method. This means that the method we pass into the delegate's constructor (in this case it's 'DisplayMessage' method) must have a method signature that
accepts a string object as an input argument, just like our delegate does. Now, you might be thinking, "why are we passing in the address of a method when we defined our delegate to accept a string object as it's input argument?" In the code above, we are telling the delegate which method to call, not which string we're
passing in. Carefully understand this concept.
  Then finally we have our 'DisplayMessage' method, which takes the string passed in by the delegate and tells it what string is to be displayed. The same approach is used while handling the events in the .NET. This topic is just to understand how delegates works in .NET.

Events:-
   Events are nothing but situations at which the message is sent to an object to signal the occurrence of the action. These actions can be caused by the user interaction or within the object itself.
  For example the class designer can create an event and raise the same through its methods and properties. These events will be captured by the object user and perform his/her required operation.
  Let us take a simple example of VB.NET Button class. Button is a class defined in System.Controls.FormsControls nameplace. The users create an instance of the Button class and select the onclick event related to the button object and write an action to be performed on click of the button.
   Actually this event is already defined in button class and will be raised when the user clicks the button. The following example shows how the event can be defined, raised in the class and used by the object user.
 Declaration:- The event member will be declared with Event keyword. Basically the event member should always be public. Because these are the members will be used by the external users.
'Declare a class which operates on the Employee collection database
'This class is used to find some summarised operation on the Employee
'collction database, which means finding the relavent employee ‘information, 'getting the
total no. of employees in the collection and ‘others - Its just 'an example to explain how
event works
Public Class EmployeeCollection
'Declare an event which will be raised after finding the data
'Keyword ‘Event’ is used the declare the events
Public Event FindResult(ByVal blnFound As Boolean)
'This method is to find the data from employee colletion database and 'raise the findresult
event to return the result
Public Sub FindData(ByVal Name As String)
'find the Employee with name and return the result as boolean, if
'the data is found then raise FindResult with True else with
'False
Dim found As Boolean
found = FineEmployee(Name)
If found Then
'Raise the event with parameter
RaiseEvent FindResult(True)
Else
'Raise the event with parameter
RaiseEvent FindResult(False)
End If
End Sub
End Class
Usage:- In order to access the events of the objects, the object should be declared with withevents clause. This is shown in the following example with form load event.
'Declare the object with WithEvents clause to create an instance
Dim WithEvents objEmpColl As EmployeeCollection = New EmployeeCollection()
Public Sub load()
'Find the Employee with name Rama in the Employee collection
objEmpColl.FindData("Rama")
End Sub
'The following event will be raised after the search operation
Private Sub objObject_FindResult(ByValue blnFound as Boolean) Handles
objObject.FindResult
If blnFound Then
MsgBox("The given Employee is Found in the collection")
Else
MsgBox("The given Employee is not Found")
End If
End Sub