18.1 Introduction to Delegates
Delegates in C# allows user to change dynamically the reference to the method in a class. A delegate is an object that can refer to a method in a class. It is a type representing to methods with a parameter list and their return type.
A delegate is a reference type variable, which holds the reference to a method. The reference can be changed at the run time by the user. Delegates are used to pass methods as arguments to other methods. They can indirectly call the methods at the run time. All the delegates are implicitly derived from the System.Delegate class.
18.2 Instantiating and using Delegates
The declaration of a delegate type is similar to a method signature. It has a return value and list of parameters of any data type.
The signature of the delegate is as shown below:
delegate result – type identifier ( [ parameters] );
Where,
· result type: The result type that matches the return type of the function
· identifier: The delegate name
· parameters: The Parameters that the function takes from the user
User must create a delegate object of the delegate type. Assign the address of the required method to the delegate object. The process is done by calling the constructor of the delegate class and passing the method name. The following code snippet shows how to assign the address of the method to a delegate variable.
public void DelegateFunction ( string Passvalue)
{
//Method to implement
}
//Delegate declaration
public delegate void MyDelegate(string ArgValue)
public void UseMethod()
{
//Delegate Instantiation
MyDelegate DelegateObject = new MyDelegate(DelegateFunction);
}
In the code snippet mentioned above, the signature and return type of the DelegateFunction() method matches with the delegate declaration of the MyDelegate delegate. The delegate holds the address of the DelegateFunction() method. The DelegateObject is of type MyDelegate. The address of the method is assigned to the object by passing the function name to the delegate constructor.
class MathOperation { public static double MultiplyByTwo(double value) { return value * 2; } public static double Square( double value ) { return value * value; } } delegate double DoubleOp(double x); class Program { static void Main( string[ ] args ) { Doubleop[ ] operations = { MathOperation.MutilplyByTwo, MathOperation.Square }; for ( int i =0; i<operations.Length; i++) { Console.WriteLine(“Using Operations [ {0} ] :”, i ); display(operations[1], 2.0 ); display(operations[i], 7.3); Console.Read(); } } static void display(DoubleOp action, double value) { double result = action (value); Console.WriteLine("Value is {0}, result of operation is {1}", value, result); Console.Read(); } }
The following code snippet shows an example of mathematical operations performed on double value.
The output for the code is as shown below:
18.3 Types of Delegates
Delegates are of two types and depending on the applications requirements, the appropriate delegate is used.
The two delegate types are:
· Single – cast delegate
· Multicast delegate
Single – cast Delegate
A single cast delegate can call only one method at a time. It is derived from System.Delegate class. It contains reference of a single method at one time.
In the above example, the single cast delegate is used. The methods MultiplyByTwo and Square are referred by the delegate, DoubleOp, one at a time.
Multicast Delegate
A multicast delegate can call multiple methods at the same time. They are derived from the System.MulticastDelegate class. It contains an invocation list of multiple methods. Multicast delegates hold the reference of more than one method. If you call a multicast delegate it will execute all the methods in the calling order. The multiple methods called one after another by the delegate. The methods should not return any value and user cannot wait to get the return value from each of these methods.
Consider the code sample for demonstrating multicast delegate.
public delegate void ShowDelegate(); class Program { public static void display1() { Console.WriteLine("The first display method is invoked"); } public static void display2() { Console.WriteLine("The second display method is invoked"); } static void Main ( string[ ] args ) { ShowDelegate s = new ShowDelegate(display1); ShowDleegate s1= new ShowDelegate(display2); s = s1+s2; s1(); Console.Read(); } }
The output for the code is as shown below
:
18.4 Using Delegates with Events
An event in C# is a way for a class to provide the notifications to clients of that class about the performed action. Applications respond to these events when they occur. Events are the messages sent by the object to indicate the occurrence of the event. They are an effective means of inter – process communication.
The events are declared and raised inside a class. They are associated with the event handlers using delegates within the same class or different classes. They are a part of the class and the same class is used to publish events. Events use the publisher and subscriber model.
A publisher is an object that contains the definition of the event and the delegate. The association of the event with the delegate is specified in the publisher class. The object of the publisher class invokes the event which is notified to other objects.
A subscriber is an object that wants to accept the event and provide a handler to the event. The delegate of the publisher class invokes the method of the subscriber class. This method in the subscriber class is the event handler.
The following figure shows the mechanism used by the publisher and subscriber objects.
Defining an Event
The definition of the event in a publisher class includes the declaration of the delegate as well as the declaration of the event based on the delegate.
public delegate void TimeToRaise();
private event TimeToRaise RingAlarm;
The following code defines a delegate named TimeToRaise and an event named RingAlarm, invokes the TimeToRise delegate when it is raised.
Subscribing an Event
The event of the publisher class can be associated with the event handler. The event handler method is associated with the event by using the delegate. When the object of publisher raises the event, the subscribing object associates the method.
Consider a class named Student. It contains a method named as WakeUp(). The requirement of the method is to be called at 6 AM. The following code snippet shows the class subscribing the event named TimeToRise.
Student s = new Student();
RingAlarm a = new TimeToRaise(s.WakeUp);
Notifying the subscribers to an Event
The subscriber object notifies to the publisher object. The event is raised to notify the handler.
In the above code, the WakeUp() method is executed through events. The following code snippet is used when user wants to notify the event to the subscribers of the event.
if(RingAlarm! = null)
{
RingAlarm();
}
In the above code, the WakeUp() method that subscribes to the event is activated.
The example to demonstrate the use of delegates with events is as shown below:
delegate void EventDelegate(); class Program { public event EventDelegate MyEvent; public void OnMyEvent() { if(MyEvent!= null) { MyEvent(); } } } class Mainclass { static void Main( string[ ] args ) { Program p = new Program(); p.MyEvent+ = handler; p.OnMyEvent(); Console.Read(); } }
The output for the code is as shown below:
18.5 Passing Event Parameters
The event class can have input at runtime on which the subscribing method is working. User needs to define a class that will pass the input to the event.
Derive the class from System.EventArgs class. The parameters are to be closed in a single class. The class supplies a special method called the accessor method to retrieve the value.
class timeInfoEventArgs:EventArgs { private int Hour; private int Minute; private int Second; public TimeInfoEventArgs ( int Hour, int Minute, int Second ) { this.Hour = Hour; this.Minute = Minute; this.Second = Second; } public int GetHour { get { return Hour; } } public int GetMinute { get { return Minute; } } public int GetSecond { get { return Second; } } }
In the above code, the TimeOfEventArgs class is the event class that will pass the value of hour, minute, second. The class declares the three accessor methods as GetHour, GetMinute, GetSecond.