Sunteți pe pagina 1din 14

Delegates and Events

Chapter 8:

Delegates and Events

Objectives
This chapter provides complete knowledge on Delegates and Events in C#. At the end
of this chapter participant would be in a position to accomplish the following activities.

Why delegates are preferred than function pointers


How to work with simple delegates
How to work with Multi cast delegates
Differences between Anonymous methods and Normal methods.
What is an event and how to use events with delegates in the applications

Page 1

Delegates and Events


Introduction
Till now, most of the applications you have developed added various bits of code
to Main(), which, in some way or another, sent requests to a given object. In objectoriented programming, it is usual practice for one object to send messages to other object.
However in real-life applications, it is quite common for an object to report back to an
object that was responsible for sending a message. This, in effect results to a two-way
communication between the objects. The methods used to call back messages are known
as Callback methods. While callback interfaces can be used to configure objects that
engage in two-way conversations, the .NET delegate type is the preferred manner to
define and respond to callbacks under the .NET platform.
In the .NET Framework, callbacks are still possible, and their functionality is
accomplished in a much safer and more object-oriented manner using delegates. In
essence, a delegate is a type-safe object that points to another method (or possibly a list
of methods) in the application, which can be invoked at a later time. Specifically
speaking, a delegate object maintains three important pieces of information:

The address of the method on which it makes calls


The arguments (if any) of this method
The return value (if any) of this method

A delegate object is a special type of object that contains the details of a method rather
than data. Delegates in C# are used for two purposes:

Callback
Event handling

The dictionary meaning of a delegate is a person acting for another person. In C#,
it really means method acting for another method. A delegate in C# is a class type object
and is used to invoke a method that has been encapsulated into it at the time of its
creation. Creating and using delegates involve four types. They include:

Delegate declaration
Delegate instantiation
Delegate method definition
Delegate invocation

A delegate declaration defines a class using the class System. Delegate as a base
class. Delegate methods are any functions whose signatures match the delegate signature
exactly. The delegate instance holds the reference to delegate methods. The instance is
used to invoke the methods indirectly.
Page 2

Delegates and Events


The important feature of a delegate is that it can be used to hold reference to a method of
any class. The only requirement is that its signature should match the signature of the
method.
Delegate declaration:
A delegate declaration is a type declaration and takes the following form:
Modifier delegate return-type delegate-name (parameters);
Delegate is the keyword that signifies that the declaration represents a class type derived
from system.delegate .The return-type indicates the return type of the delegate.
Parameters identifies the signature of the delegate .The delegate-name is any valid C#
identifier and is the name of the delegate that will be used to instantiate delegate objects.
delegate void SimpleDelegate ();
delegate int Mathoperation (int x, int y);
public delegate int compareItem(object o1, object o2);
private delegate string GetAString();
delegate double DoubleOperation(double x);
A delegate may be defined in the following classes:

Inside a class
Outside all classes

When the C# compiler processes delegate types, it automatically generates a sealed class
deriving from System.MulticastDelegate.
Delegate Method:
The method whose references are encapsulated into a delegate instance are
known as delegate methods or callable entities. The signature and return type of
delegate method must exactly mach the signature and return type of the delegate.
One feature of delegates, as pointed out earlier, is that they are type-safe to the extent
that they ensure the matching of signatures of the delegate methods.
However, they do not care

Page 3

Delegates and Events

What type of object method is being called against ,and


Whether the method is a static or an instance method.

The delegate
Delegate void Delegate1();
Can encapsulate references to the following method:
Public void F1()
//instance method
{
Console. WriteLine(F1);
}
Static public void F2()
//static method
{
Console.WriteLine(F2);
}
Delegate Instantiation:
Although delegates are of class type and behave like classes, C# provides a
special syntax for instantiating their instances. A delegate-creation-expression is used to
create a new instance of a delegate.
New delegate-type(expression)
The delegate-type is the name of the delegate declares earlier whose object is to be
created. The expression must be a method name or a value of a delegate-type. If it is a
method name its signature and return type must be the same as those of the delegate.
Consider the following code:
//delegate declaration
Delegate int ProductDelegate (int x, int y);
Class Delegate
{
Static int Product (int a, int b)
{
return (a*b);
}
//delegate instantiation
ProductDelegate p= new productDelegate (Product);
}

Page 4

Delegates and Events

Delegate Invocation:
C# uses a special syntax for invoking a delegate. When a delegate is invoked, it in
turn invokes the method whose reference has been encapsulated into the delegate,(only if
their signatures match).Invocation takes the following form:
Delegate_object (parameters list)
The optional parameters list provides values for the parameters of the method to be
used.
Example:
delegate int ArithOp(int x, int y);
class MathOperation
{
//delegate method definition
public static int Add(int a, int b)
{
return (a + b);
}
public static int Sub(int a, int b)
{
return (a - b);
}
}
class Program
{
static void Main(string[] args)
{
//Delegate instances
ArithOp operation1 = new ArithOp(MathOperation.Add);
ArithOp operation2 = new ArithOp(MathOperation.Sub);
//invoking instances
int result1 = operation1(100, 200);
int result2 = operation2(200, 100);
Console.WriteLine("Result1= " + result1);
Console.WriteLine("Result2= " + result2);
Page 5

Delegates and Events


}
}

Inheritance of delegates
public delegate void deleg1();
class baseclass
{
public deleg1 del;
}
class DerivedClass : baseclass
{
public DerivedClass()
{
del = new deleg1(func1);
del();
//show();
del = new deleg1(func2);
del();
//show();
}
public void func1()
{
Console.WriteLine("derived class method func1()");
}
public void func2()
{
Console.WriteLine("Derived Class method func2()");
}
}
class Program
{
static void Main(string[] args)
{
DerivedClass dvobj = new DerivedClass();
}
}
}
Page 6

Delegates and Events

Multicast delegate:
We have seen so far that a delegate can invoke only one method (whose reference
has been encapsulated into the delegate). However, it is possible for certain delegates to
hold and invoke multiple methods. Such delegates are called Multicast delegates.
Multicast delegates are also known as combinable delegates.
If D is a delegate and d1, d2, d3, and d4 are instances of D, then the statements
d3=d1+d2

//d3 refers to two methods

d4=d3-d2; //d4 refers to only d1 method


are valid provided that the delegate instances d1 and d2 have already been initialized with
method references.
delegate void MulticastDelegate();
class example
{
public void Display()
{
Console.WriteLine("Delhi");
}
public void Print()
{
Console.WriteLine("India");
}
}
class Program
{
static void Main(string[] args)
{
example e = new example();
MulticastDelegate m1 = new MulticastDelegate(e.Display);
MulticastDelegate m2 = new MulticastDelegate(e.Print);
MulticastDelegate m3 = m1 + m2;
MulticastDelegate m4 = m3 + m1;
MulticastDelegate m5 = m3 - m2;
m3();
m4();
m5();
Page 7

Delegates and Events


Console.ReadLine();
}
}
delegate void FunctionToCall(ref int X);
class MainClass
{
public static void Add2(ref int x)
{
x += 2;
}
public static void Add3(ref int x)
{
x += 3;
}
static void Main(string[] args)
{
FunctionToCall functionDelegate ;
functionDelegate = Add2;
functionDelegate += Add3;
int x = 5;
functionDelegate(ref x);
Console.WriteLine("Value: {0}", x);
}
}
Anonymous Methods:
Creating anonymous methods is essentially a way to pass a code block as a
delegate parameter. By using anonymous methods, you reduce the coding overhead in
instantiating delegates by eliminating the need to create a separate method. It is an error
to have a jump statement such as goto, break, or continue, inside the anonymous method
block whose target is outside the block.

Page 8

Delegates and Events


class Program
{
delegate int FunctionCall(int num);
static void Main(string[] args)
{
FunctionCall del = delegate(int x)
{
return x + 20;
};
Console.WriteLine(del(5));
Console.WriteLine(del(6));
}
}

Events:
An event in C# is a way for a class to provide notifications to clients of that class when
some interesting thing happens to an object. The most familiar use for events is in
graphical user interfaces; typically, the classes that represent controls in the interface have
events that are notified when the user does something to the control (for example, click a
button).
As a shortcut to having to build custom methods to add or remove methods to a
delegates invocation list, C# provides the event keyword. These delegate member
variables are always declared private, and therefore they are not directly exposed from
the object firing the event. Defining an event is a two-step process.

First, you need to define a delegate that will hold the list of methods to be called
when the event is fired.
Next, you declare an event (using the C# event keyword) in terms of the related
delegate.

Declaring an event To declare an event inside a class, first a delegate type for the event
must be declared, if none is already declared.
public delegate void ChangedEventHandler(object sender, EventArgs e);
EventArgs is the base class for classes containing event data. The delegate type defines
the set of arguments that are passed to the method that handles the event. Multiple events

Page 9

Delegates and Events


can share the same delegate type, so this step is only necessary if no suitable delegate
type has already been declared.
Next, the event itself is declared.

public event ChangedEventHandler Changed;


When the compiler processes the event keyword, you are automatically provided
with registration and unregistration methods as well as any necessary member
variables for your delegate types. An event is declared like a field of delegate
type, except that the keyword event precedes the event declaration, following the
modifiers. Events usually are declared public, but any accessibility modifier is
allowed.
Invoking an event Once a class has declared an event, it can treat that event just like a
field of the indicated delegate type. The field will either be null, if no client has hooked
up a delegate to the event, or else it refers to a delegate that should be called when the
event is invoked. Thus, invoking an event is generally done by first checking for null and
then calling the event.
if (Changed != null)
Changed(this, e);
Invoking an event can only be done from within the class that declared the event.
An event is a delegate type class member that is used by the object or class to provide a
notification to other objects that an event has occurred. The client object can act on an
event by adding an event handler to the event.
Events are declared using the simple event declaration format as follows:
Modifier event type event-name;
The type of an event declaration must be a delegate type and the delegate must be as
accessible as the event itself. The event-name is any valid C# variable name. event is a
keyword that signifies that the event-name is an event.
Example of event declaration are:
Public event EventHandler Click;
Public event RateChange Rate;
Page 10

Delegates and Events

EventHandler and RateChange are delegates and Click and Rate are events.
Since events are based on delegates, we must first declare a delegate and then declare an
instance of the delegate using the keyword event.
Hooking up to an event From outside the class that declared it, an event looks like a
field, but access to that field is very restricted. The only things that can be done are:

Compose a new delegate onto that field.

Remove a delegate from a (possibly composite) field.

This is done with the += and -= operators. To begin receiving event invocations, client
code first creates a delegate of the event type that refers to the method that should be
invoked from the event. Then it composes that delegate onto any other delegates that the
event might be connected to using +=.
// Add "ListChanged" to the Changed event on "List":
List.Changed += new ChangedEventHandler(ListChanged);
When the client code is done receiving event invocations, it removes its delegate from the
event by using operator -=.
// Detach the event and delete the list:
List.Changed -= new ChangedEventHandler(ListChanged);
Example 1
class MyClass
{
public delegate void Eventhandler(string message);
public event Eventhandler logEvent;
public void process()
{
if (logEvent != null)
{
logEvent("Process () begins");
}
}
}
class Program
{
Page 11

Delegates and Events


public static void display(string s)
{
Console.WriteLine(s);
}
static void Main(string[] args)
{
MyClass objMyClass = new MyClass();
objMyClass.logEvent +=new MyClass.Eventhandler(display);
objMyClass.process();
Console.ReadLine();
}
}
Example 2:
delegate void ButtonEventHandler(object source, int clickCount);
class Button
{
//declaring the event
public event ButtonEventHandler ButtonClick;
//Function to trigger the event
public void clicked(int count)
{
Console.WriteLine("\nInside Clicked !!!");
//Invoking all the event handlers
if (ButtonClick != null) ButtonClick(this, count);
}
}
public class Dialog
{
public Dialog()
{
Button b = new Button();
//Adding an event handler
b.ButtonClick += new ButtonEventHandler(onButtonAction);
//Triggering the event
b.clicked(1);
b.ButtonClick += new ButtonEventHandler(onButtonAction);
Page 12

Delegates and Events


b.clicked(1);
//Removing an event handler
b.ButtonClick -= new ButtonEventHandler(onButtonAction);
b.clicked(1);
b.ButtonClick -= new ButtonEventHandler(onButtonAction);
b.clicked(1);
}
static void Main()
{
new Dialog();
}
//Event Handler function
public void onButtonAction(object source, int clickCount)
{
Console.WriteLine("Inside Event Handler !!!");
}
}

Points to Remember
Delegates provide a built-in, language-supported mechanism for defining and
executing callbacks.
.NET delegate type is the preferred manner to define and respond to callbacks
under the .NET platform.
A delegate in C# is a class type object and is used to invoke a method that has
been encapsulated into it at the time of its creation.
Delegate methods are any functions whose signatures match the delegate
signature exactly.
It is possible for certain delegates to hold and invoke multiple methods. Such
delegates are called Multicast delegates.
When the C# compiler processes delegate types, it automatically generates a
sealed class deriving from System.MulticastDelegate, which contains Invoke(),
BeginInvoke() and EndInvoke() methods.
An event in C# is a way for a class to provide notifications to clients of that class
when some interesting thing happens to an object.
Page 13

Delegates and Events


To declare an event inside a class, first a delegate type for the event must be
declared.
Invoking an event can only be done from within the class that declared the event.
Check YourSelf

Exercise:
Write a Program to Encapsulate more than one method into the delegate and
invoke the methods individually based on requirement.
Write a Program to Show an example for returning a delegate from a method.
Write a Program to Pass delegate as a Parameter for a method and construct the
class.
Write a Program by showing the differences between delegates with anonymous
method and delegates with normal methods.
Write the Scenarios where to use delegates and where to use interfaces.

Page 14