Click here to Skip to main content
15,867,330 members
Articles / Desktop Programming / Windows Forms
Article

Unraveling Delegates & Events

Rate me:
Please Sign up or sign in to vote.
3.76/5 (24 votes)
21 Feb 2006CPOL5 min read 69.1K   54   17
This article briefs about Delegates and focuses on differentiating Delegates & Events

Contents

  • Introduction
  • What are Delegates
  • Typesafe Delegates
  • Declaring, Instantiating and Invoking Delegates
  • Events
  • Conclusion

Introduction

Delegates & Events are often the most ignorant pieces in the .<stockticker>NET Framework. Rumor has it; they instill fear in the curious minds by their sheer complexity. I studied a great deal of articles in an effort to demystify the unknown, but I really found out there wasn't anything colossal here. Through my article, I will try my hand at exploring the nature of Delegates & Events. Now let’s get down to business.

What are Delegates

If you ask anybody, they would say:

Delegates are similar to Function pointers in C/C++.

Well said, but what are function pointers.

Function pointers are the pointer variables that point to a memory address of a function. So invoking that function pointer would call simply call the underlying function.

Definition

  • A Delegate is a class whose object store references to methods
  • A Delegate encapsulates a method with a certain signature

We use delegates inadvertently in our day-to-day coding.

Refer to the code below:

C#
this.DataGrid1.ItemDataBound += new
    System.Web.UI.WebControls.DataGridItemEventHandler(
    this.DataGrid1_ItemDataBound);

When we use DataGrid’s ItemDataBound event, delegates are at work.

DataGrid’s ItemDataBound is the event of type DataGridItemEventHandler Delegate pointing to function DataGrid1_ItemDataBound.

Do not indulge into this right now as I will come to Events later on in the article.

Typesafe Delegates

Are Delegates Any Different from their C/C++ Counterparts (Function Pointers)

Yes, delegates in .<stockticker>NET Framework are typesafe. This means that Delegate signature should match that of the function it points to (encapsulates).

You will get a compile-time error if that’s not the case.

On the other hand, a function pointer in C points to a memory location but it knows nothing about the parameters and the return type of the function unlike delegates.

Declaring, Instantiating and Invoking Delegates

Declaration

Let’s declare a simple delegate:

C#
public delegate bool SmartDelegate(string name, int salary);

This delegate signature signifies that it will encapsulate methods with return type as bool and parameters as string and int.

The function that this delegate references would look something like this:

C#
public bool Myfunc(string name, int salary)

So What Exactly Happens When a Delegate Declaration is Executed?

A delegate declaration is a class declaration that mimics a function-like declaration. In other words, a class is defined that is derived from a MulticastDelagate class and can be actually deciphered as:

C#
public class SmartDelegate : System.MulticastDelegate 

Instantiation

C#
SmartDelegate smartDelegate = new SmartDelegate(MyFunc);

Notice how you instantiate a delegate, just like you would instantiate a class, simply because a delegate is a class.

You can add to the delegates invocation list by using the “+=” operator.

Instantiation of a delegate includes passing the function name (MyFunc) in its constructor. Notice, you do not include the round braces of the function.

Excluding the braces simply means passing the address of the function.

Note: An instance of a delegate can refer to any instance or static method, provided the signature of the method matches the signature of the delegate.

Invoking Delegate

Simply call the delegate instance:

C#
smartDelegate();

So What Happens When You Actually Call the Delegate Instance?

Invoking a delegate gets translated as follows:

C#
sampleDelegate.Invoke()

The Invoke function calls the function (MyFunc) in turn using the address of the function stored in the delegate instance.

Events

Let’s shift our energy to events.

Events are the outcome of an action. Yes, they are but there is more to this Delegates & Events tale. Infact, my prime reason to write this article was to explore the difference between the two. We could have simply done away with just having delegates, but why do we need events.

Events are really restricted delegates.

Playing with Events

Let’s start by declaring an event.

C#
public static event SmartDelegate SmartEvent;

Again adding a target to an event is a similar procedure to that of delegates:

C#
SmartEvent += new SmartDelegate(Myfunc);

Comparing Event & Delegate Declarations

C#
public delegate void SmartDelegate();        // Delegate Declaration
public SmartDelegate smartDelegate;          //Statement 1
public event SmartDelegate smartEvent;       //Statement 2

If you compare statement 1 and statement 2, it seems that the event keyword is only a modifier here. But what does this modifier do?

Let me explain.

Let’s say there is a ClassA that defines a delegate field and an event both based on type SmartDelegate.

C#
namespace MyExample
{
    public delegate void SmartDelegate();

    public class ClassA
    {
        public SmartDelegate smartDelegate;
        public event SmartDelegate smartEvent;

        public ClassA()
        {
        }
    }
}

Now a certain class Client accesses just the delegate field.

C#
namespace MyExample
{
    class Client
    {
        [STAThread]
        static void Main(string[] args)
        {

            ClassA objA = new ClassA();
            objA.smartDelegate += new SmartDelegate(MyFunc1); //statement 1
            objA.smartDelegate = new SmartDelegate(MyFunc2);  //statement 2
            objA.smartDelegate();
        }

        public static void MyFunc1()
        {
            Console.WriteLine("MyFunc1");
        }

        public static void MyFunc2()
        {
            Console.WriteLine("MyFunc2");
        }
    }

Check the output, on console window it will only display:

MyFunc2

Why?

Because statement2 resets the delegate instance throwing away the statement 1 invocation.

If statement 2 was used with “+=” operators, the output would have been:

MyFunc1
MyFunc2

Let’s rewrite the class Client by just replacing statement 2 with event.

C#
namespace MyExample
{
 class Client
 {
  [STAThread]
  static void Main(string[] args)
  {
   ClassA objA = new ClassA();

   objA.smartDelegate += new SmartDelegate(MyFunc1); //statement 1
   //statement 2 would produce a compilation error.
   objA.smartEvent = new SmartDelegate(MyFunc2);

   objA.smartEvent();  //statement 3  would produce a compilation error
  }

  public static void MyFunc1()
  {
   Console.WriteLine("MyFunc1");
  }
  public static void MyFunc2()
  {
   Console.WriteLine("MyFunc2");
  }
}

Statement 2 would give a compilation error because an event would put a restriction and not let the delegate to reset. Using “+=” operator on statement 2 would execute properly.

Therefore, through events you can only add/remove from the delegate’s invocation list. But never reset the delegate by using “=”.

Also, statement 3 produces an error because you cannot invoke an event outside the class that defines the event.

Here, invoking the event in class Client is wrong.

Now, I'll modify the classes to run the code properly.

C#
namespace MyExample
{
    public delegate void SmartDelegate();

    public class ClassA
    {
        public SmartDelegate smartDelegate;
        public event SmartDelegate smartEvent;

        public ClassA()
        {
        }

        public void FireEvent()
        {
            smartEvent();  //Fires the event
        }
    }
}

namespace MyExample
{
    class Client
    {
        [STAThread]
        static void Main(string[] args)
        {
            ClassA objA = new ClassA();

            objA.smartDelegate += new SmartDelegate(MyFunc1); //statement 1
            objA.smartEvent += new SmartDelegate(MyFunc2);    //statement 2
            objA.smartDelegate(); // invokes the Delegate
            objA.FireEvent();     // invokes the Event
        }

        public static void MyFunc1()
        {
            Console.WriteLine("MyFunc1");
        }

        public static void MyFunc2()
        {
            Console.WriteLine("MyFunc2");
        }
    }

The output on the console window is as follows:

MyFunc1
MyFunc2

Some Properties that Events Exhibit

  1. Events can only be invoked by the class that defined it.
  2. Events can be included in interfaces whereas interfaces cannot contain fields of type delegate.
  3. Events cannot reset the delegate invocation list by using “=” outside its class definitions. Events can only add/remove to the handler by using “+=” and “-=” respectively.

Conclusion

Including Event modifier to the delegate declaration only lets the adding/removing of the target to the invocation list & constrains its invocation from outside the class that defines it.

This is exactly where events come into the picture and prevent such a situation.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
India India
I am working as a Software Eng. having an experience of 3 years on Microsoft Technologies platform being .NET.
My interests include listening to music & jamming with my band "TechTonica" as a drummer.

Comments and Discussions

 
Generalwhen to use delegates Pin
umesh shahane22-Feb-06 1:35
umesh shahane22-Feb-06 1:35 

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.