Click here to Skip to main content
15,884,176 members
Articles / Programming Languages / C#
Article

Delegates and Events

Rate me:
Please Sign up or sign in to vote.
4.11/5 (38 votes)
16 Aug 20036 min read 216.8K   2   58   17
This article briefly introduces the concepts of delegates, events and how they are used in the .NET framework's base class libraries.

Introduction

Delegates and Events are two very powerful features of .NET. Events are the cornerstone of GUI programming and Delegates are used in implementing them. In this article, I discuss briefly how delegates work and how they are made use of to implement events.

Table of Contents

What is a delegate?

Delegates in the .NET framework are equivalent to function pointers. However, the C# Language Specification also adds: "unlike function pointers, delegates are object oriented and type-safe”.

Delegates allow you to pass references of entry points to methods and invoke them without making an explicit method call. It also defines the signature of the method it can call.

For example:

C#
public delegate int MyDelegate(string somevalue);

This delegate may be used to invoke methods that return an integer and take a string as a parameter. In order to make use of this delegate, you need to instantiate it, to specify the method that needs to be called.

For example:

C#
public void MyMethod()
{
    MyDelegate a = new MyDelegate(MyDelegateMethod);
}

Here MyDelegateMethod is a method that has a signature similar to that of MyDelegate.

Note: If signatures of method and delegate do not match, the C# compiler reports an error such as:

td.cs(38,46): error CS0123: Method 'DelegateDemo.SampleClient.MyEvent()' 
does not match delegate 'void DelegateDemo.CustomTextEvent()'

A delegate is used to invoke a method similar to how a method call is made.

For example:

C#
a("This is a test invocation");

Thus, there are three steps in defining and using delegates:

  • Declaration
  • Instantiation and
  • Invocation

A complete example follows:

C#
using System;


namespace SimpleDelegateExample{

public delegate void SimpleDelegate();

class TestDelegate

{
    public static void ActualFunction()
    {
        Console.WriteLine("called by delegate..");
    }
    public static void Main(){
        SimpleDelegate sd = new SimpleDelegate(ActualFunction);
        sd();
    }

}// end class TestDelegate

}// end namespace SimpleDelegateExample

A couple of interesting points to note …

A delegate does not know or care about the class of the object that it references. Any object will do; all that matters is that the method's argument types and return type match the delegate's. This makes delegates perfectly suited for "anonymous" invocation.

If an invoked method throws an exception, the method stops executing, the exception is passed back to the caller of the delegate, and remaining methods in the invocation list are not invoked. Catching the exception in the caller does not alter this behavior.

How delegates work?

The .NET framework documentation details how delegates work.

“A delegate declaration defines a class that is derived from the class System.Delegate. A delegate instance encapsulates an invocation list, which is a list of one or more methods, each of which is referred to as a callable entity. For instance methods, a callable entity consists of an instance and a method on that instance. For static methods, a callable entity consists of just a method. Invoking a delegate instance with an appropriate set of arguments causes each of the delegate instance's callable entities to be invoked with the given set of arguments.”

Events

The C# programmer’s reference defines an event as follows:

“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)."

Declaring an event is directly tied to a delegate. A delegate object encapsulates a method so that it can be called anonymously. An event is a mechanism by which a client class can pass in delegates to methods that need to be invoked whenever “something happens”. When it does, the delegate(s) given to it by its clients are invoked.

To declare an event in C# use the following syntax:

C#
public delegate void testDelegate(int a);
public event testDelegate MyEvent;

Once an event is declared, it must be associated with one or more event handlers before it can be raised. An event handler is nothing but a method that is called using a delegate. Use the += operator to associate an event with an instance of a delegate that already exists.

For example:

C#
Myform.MyEvent += new testEvent(MyMethod);

An event handler may also be detached as follows:

C#
MyForm.MyEvent -= new testEvent(MyMethod);

In C#, events may be raised by just calling them by a name similar to method invocation, say MyEvent(10). The example given in the next section will help you understand events better.

How does the event keyword work ?

Whenever an event is defined for a class, the compiler generates three methods that are used to manage the underlying delegate… i.e.:

  • add_<EventName>:

    This is a public method that calls the static Combine method of System.Delegate in order to add another method to its internal invocation list. This method is however not used explicitly. The same effect is achieved by using the += operator as specified before.

  • remove_<EventName>:

    This is also a public method that calls the static Remove method of System.Delegate in order to remove a receiver from the event’s invocation list. This method is also not called directly. Its job is done by the -= operator.

  • raise_<EventName>:

    A protected method that calls the compiler generated Invoke method of the delegate, in order to call each method in the invocation list.

Delegates and Events in Windows Forms

Default delegates are provided for the events of the controls and classes of the .NET Framework base class library. When using Windows Forms to create rich client applications, events can be handled in two ways…

  • By declaring a method that has a signature that is the same as the corresponding event handler delegate and then registering the method as a handler (using +=).
  • By overriding the corresponding event method, when your class is a subclass of the Control class.

For example, the Paint event (equivalent to a WM_PAINT) in a Windows forms application can be handled as follows:

Registering event handlers with delegates:

Declare a method with the same return types and arguments as the PaintEventHandler delegate:

C#
static void MyPaintHandler(object sender, PaintEventArgs pea){
// process
}

and then install this handler for a particular instance…

C#
myform.Paint += new PaintEventHandler(MyPaintHandler);

Overriding member functions:

Inside a class derived from Form (Control), you can simply override the OnPaint method:

C#
protected override void OnPaint(PaintEventArgs pea){
// process
}

At this point, it is quite natural to think that the base class method (which can be overridden to handle an event) is just an event handler, that has already been installed. It is actually the other way around. It is the responsibility of the base class method to actually invoke all the installed event handlers. Let me give an example to illustrate this point:

C#
using System;

using System.Windows.Forms;

namespace DelegateDemo{

public delegate void CustomTextEvent();

class CustomTextForm : Form

{
    private string m_sText=null;
    public event CustomTextEvent CustomTextChanged;
    public string CustomText
    {
        get
        {
            return m_sText;
        }
        set
        {
            m_sText = value;
            OnCustomTextChanged();
        }
    }
    protected virtual void OnCustomTextChanged()
    {
        if(CustomTextChanged!= null)
            CustomTextChanged();
    }

}// end class CustomTextForm

class SampleClient
{
    public static void Main(){
        CustomTextForm a = new CustomTextForm();
        a.CustomTextChanged += new CustomTextEvent(SampleClient.MyEvent);
        a.CustomText = "Welcome !";
        Application.Run(a);
    }
    public static void MyEvent()
    {
        Console.WriteLine("Custom text changed");
    }

}// end class SampleClient

}// end namespace SampleDelegateDemo

Code Discussion:

For the sake of discussion, assume you need to write a custom Form class that has a property called CustomText. It is actually a string that can be set or obtained. Whenever the text is set, an event is fired. This is declared as:

C#
public event CustomTextEvent CustomTextChanged; 

and the corresponding delegate is also defined:

C#
public delegate void CustomTextEvent();

There is also an event handling method of the base class (your class) that is called whenever this event occurs. This is given as:

C#
protected virtual void OnCustomTextChanged()
{
if(CustomTextChanged!= null)
CustomTextChanged();
}

The client class also registers a new event handler …

C#
a.CustomTextChanged += new CustomTextEvent(SampleClient.MyEvent);

When you run this sample, the MyEvent method is called when the CustomText property is changed.

Note:

The following code is mandatory:

C#
if(CustomTextChanged!= null)
CustomTextChanged();

because CustomTextChanged is likely to be null, if no handlers have been registered at the time the CustomText property is set.

The OnCustomChanged method is declared virtual so that it can be overridden by subclasses.

Further Reading

Once you are quite familiar with delegates, you would find the following articles interesting:

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
India India
I started programming with GW-BASIC and then moved onto C/C++ and assembly (under DOS)

My experience with Windows, started when I got a Pentium I, powered by Windows 95, when I was in Standard 9. I have since been programming extensively in Windows. My chief interest is the Win32 API. I also have some experience with VB, MFC, ASP and COM.

As with many other Windows developers I thoroughly enjoy programming in .NET (C# and Managed C++)

Comments and Discussions

 
GeneralRe: More info on Delegates might be helpfull. Pin
Anonymous19-Aug-03 14:54
Anonymous19-Aug-03 14:54 
GeneralRe: More info on Delegates might be helpfull. Pin
KaushikS19-Aug-03 14:55
KaushikS19-Aug-03 14:55 
Generaladd and remove Pin
Lars Heyden17-Aug-03 18:11
Lars Heyden17-Aug-03 18:11 
GeneralRe: add and remove Pin
Anonymous17-Aug-03 18:19
Anonymous17-Aug-03 18:19 
GeneralRe: add and remove Pin
KaushikS17-Aug-03 18:22
KaushikS17-Aug-03 18:22 
GeneralMore details Pin
Julien Couvreur17-Aug-03 11:29
Julien Couvreur17-Aug-03 11:29 
GeneralRe: More details Pin
KaushikS17-Aug-03 16:15
KaushikS17-Aug-03 16:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.