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

Delegates

Rate me:
Please Sign up or sign in to vote.
2.93/5 (7 votes)
13 Jan 2009CPOL5 min read 24.7K   23   3
Delegate is type-safe object which can point to any function to invoke them synchronously and asynchronously

Calling functions/Methods synchronously & asynchronously using Delegates<o:p>

Being a programmer, it’s almost daily routine to write such methods which take plenty of processor cycles/time to perform some action. For example some database operation/transactions, while using web services or Remote Procedure Calling (RPC), File I/O operations, etc. <o:p>

<o:p>

To call such functions or methods which take plenty of time, user needs to wait for process to complete and some time in exceptional cases application hangs up if process couldn’t get complete for some reason. But in both cases user gets annoy and User Interface (UI) gets freeze until process completed if you have to call them synchronously. <o:p>

<o:p>

In synchronous way of communication, caller process/thread needs to wait until called process/thread got complete but in case of asynchronous caller just need to send request to perform operation and get back means. It doesn’t need to wait for called process/thread completion. <o:p>

Thanks to .Net team as they provide managed code Type-Safe mechanism to point any method or function and introduced Delegate. Delegates are like Function Pointer in C/C++ but Type-Safe, flexible by means of inheritance and powerful by means of referencing multiple methods as well as powerful by means of asynchronicity and supporting callback and calling them. <o:p>

<o:p>

Delegate:<o:p>

<o:p>

Delegate is type-safe object which can point to any function to invoke them synchronously and asynchronously. A single delegate has power to point to multiple sub routines (such functions whose return type is VOID). It invokes them at a time. Such delegates are known as Multicast delegate.  <o:p>

<o:p>

How to define Delegate:<o:p>

A delegate is quite easy to implement. Defining delegate is almost like any function as following is definition of simple function in C#.<o:p>

<o:p>

Return_Type Function_Name(Params); //Pseudo Code<o:p>

int AddTwoNumbers(int Num1, int Num2); //C# Code<o:p>

And to define delegate, we just need to add delegate keyword like below:<o:p>

delegate Return_Type Function_Name(Params); //Pseudo Code<o:p>

delegate int AddTwoNumbers(int Num1, int Num2); //C# Code<o:p>

<o:p>

I hope it’s easier than Rocket Science. :P<o:p>

<o:p>

<o:p>


Calling method synchronously Example:<o:p>

<o:p>

Delegates can call methods in synchronously and asynchronously manners.<o:p>

Invoke method uses to call target method synchronously for same Thread.

<span class="kwd">namespace</span> NSDelegate
{
    <span class="kwd">public class</span> HeavyProcess
    {
        <span class="kwd">public string</span> GetWeatherInfo(<span class="kwd">int</span> zip)
        {
            <span class="cmt">//Call weather.com web service and get information about weather</span>
        }

        <span class="kwd">public void</span> MakeScriptOfDatabase()
        {

            <span class="cmt">//Make Database Schema and data script and write on .txt File</span>
        }
    }

    <span class="kwd">public class</span> MyDelegateExample
    {
        <span class="cmt">//Following delegate can point to those functions 
        //which take integer value and return string value</span>
        <span class="kwd">public delegate string</span> dlgGetWeatherInfo(<span class="kwd">int</span> zip);
        HeavyProcess hp = <span class="kwd">new</span> HeavyProcess();
        <span class="kwd">public</span> MyDelegateExample()
        {
            <span class="cmt">//Create instance of delegate and give reference of method</span>
dlgGetWeatherInfo dlgWeatherInfo = <span class="kwd">new</span> dlgGetWeatherInfo(hp.GetWeatherInfo);
            <span class="cmt">//invoke method to call referenced method/function</span>
            <span class="kwd">string</span> strWeatherInfo = dlgWeatherInfo.Invoke(54000);
        }
    }
}
Calling Method Asynchronously <o:p>

BeginInvoke method used to call method asynchronously and EndInvoke methods have access on return value and input or output parameters. When we use BeginInvoke method request, it goes to queue and handles return to caller thread for proceed. Than/and target/called method would be run in another thread from thread pool. These methods would run concurrently which seems as both are running in parallel. <o:p>

BeginInvoke method returns IAsyncResult which uses to pass as parameter whilst invoking EndInvoke method. <o:p>

We can use two ways for determine to know that when to call EndInvoke method:<o:p>

1). IAsyncResult object. We need to get WaitHandler and call WaitOne method to block execution until the WaitHandle get signal.

<span class="kwd">namespace</span> NSDelegate
{
    <span class="kwd">public class</span> HeavyProcess
    {
        <span class="kwd">public string</span> GetWeatherInfo(<span class="kwd">int</span> zip)
        {
            <span class="cmt">//Call weather.com web service and get information about weather</span>
        }
    }
    <span class="kwd">public class</span> MyDelegateExample
    {
        <span class="cmt">//Following delegate can point to those functions 
        //which take integer value and return string value</span>

        <span class="kwd">public delegate string</span> dlgGetWeatherInfo(<span class="kwd">int</span> zip);

        HeavyProcess hp = <span class="kwd">new</span> HeavyProcess();

        <span class="kwd">public</span> MyDelegateExample()
        {
            <span class="cmt">//Create instance of delegate and give reference of method</span>
dlgGetWeatherInfo dlgWeatherInfo = <span class="kwd">new</span> dlgGetWeatherInfo(hp.GetWeatherInfo);

            <span class="cmt">//invoke method to call referenced method/function</span>
            IAsyncResult async = dlgWeatherInfo.BeginInvoke(54000, <span class="kwd">null</span>, <span class="kwd">null</span>);
            <span class="cmt">// TO DO CODE to perform any other operation
            // wait for the WaitHandle to be signaled.</span>
              async.AsyncWaitHandle.WaitOne();
            <span class="cmt">//receive the results</span>
            <span class="kwd">string</span> strWeatherInfo = dlgWeatherInfo.EndInvoke(async);
        }
    }
}

<o:p> 2). Callback Delegate and <st1:place w:st="on"><st1:placename w:st="on">Get <st1:placename w:st="on">Async <st1:placetype w:st="on">State:<o:p>

You might be wondering about null parameters which I have passed in BeginInvoke method in prior example code. Instead of first null parameter which I have passed, we can pass reference of another method which we want to be called automatically by the target method/thread when target method completes execution. Ins’t it better than first solution. Anyhow for that purpose we use AsyncCallback and give reference of static Method which return type is void and (takes IAsync object which return by BeginInvoke method.) <o:p>

Second null parameter could be replaced by any object type data/value which used to represent state of method.
<span class="kwd">namespace</span> NSDelegate
{
    <span class="kwd">public class</span> HeavyProcess
    {
        <span class="kwd">public string</span> GetWeatherInfo(<span class="kwd">int</span> zip)
        {
            <span class="cmt">//Call weather.com web service and get information about weather</span>
        }
    }
    <span class="kwd">public class</span> MyDelegateExample
    {
        <span class="cmt">//Following delegate can point to those functions 
        //which take integer value and return string value</span>
        <span class="kwd">public delegate string</span> dlgGetWeatherInfo(<span class="kwd">int</span> zip);
        HeavyProcess hp = <span class="kwd">new</span> HeavyProcess();
        
	<span class="kwd">public</span> MyDelegateExample()
        {
            <span class="cmt">//Create instance of delegate and give reference of method</span>
            dlgGetWeatherInfo dlgWeatherInfo = <span class="kwd">new</span> dlgGetWeatherInfo(hp.GetWeatherInfo);
            <span class="cmt">//invoke method to call referenced method/function</span>
            IAsyncResult async = dlgWeatherInfo.BeginInvoke(54000, <span class="kwd">new</span> AsyncCallback
(GetResultByCallback), <span class="st">"Did you get message? :P"</span>);
        }
        <span class="kwd">static void</span> GetResultByCallback(IAsyncResult asyncResult)
        {
             <span class="cmt">//As we couldn't access to IAsyncResult object which we initiated in Caller //method so 
            // we typecase and assign to keep it locally for this method</span>
              System.Runtime.Remoting.Messaging.AsyncResult result = 
(System.Runtime.Remoting.Messaging.AsyncResult) asyncResult;
            <span class="cmt">//Get control over that AsyncResult object to call its endInvoke method to //finalize async processing</span>
            dlgGetWeatherInfo dlg = (System.Runtime.Remoting.Messaging.AsyncResult)result.AsyncDelegate;
            <span class="cmt">//receive the results</span>
            <span class="kwd">string</span> strWeatherInfo = result.EndInvoke(asyncResult);
            <span class="cmt">//Get State result which in our case was "Did you get message? :P"</span>
            <span class="kwd">string</span> strState = (<span class="kwd">string</span>)result.AsyncState; 
        }
    }
}

<o:p>

EndInvoke method must be called to complete delegates’ asynchronous call.<o:p>

Multicast Delegate:<o:p>

<o:p>

Power of delegate is not over at calling single method synchronously or asynchronously. Delegates can be used to call multiple methods as delegate object can have reference of multiple methods but methods return type should be void. <o:p>

<o:p>

Internally Multicast delegates are a Link List of delegate objects and each node contains reference of prior delegate. <o:p>

<o:p>

Delegates achieve this functionality by inheriting Multicast Delegate class under System namespace. Multicast delegates can keep or point to multiple handlers of different methods. It can be execute at single call. <o:p>

<o:p>

<o:p>

Calling multiple methods at once synchronously using Multicast delegate<o:p>

<o:p>

<o:p>

Covariance and Contra variance Delegates

<span class="kwd">namespace</span> NSDelegate
{
    <span class="kwd">public class</span> HeavyProcess
    {
        <span class="kwd">public void</span> MakeScriptOfDatabase()
        {
            <span class="cmt">//Make Database Schema and data script and write on .txt File</span>
        }

        <span class="kwd">public void</span> ETW()
        {
            <span class="cmt">//Perform ETW Operations</span>
        }
    }

    <span class="kwd">public class</span> MyDelegateExample
    {
        <span class="cmt">//Following delegate can point to those functions 

        //which take integer value and return string value</span>
        <span class="kwd">public delegate string</span> dlgDBOperations();
        HeavyProcess hp = <span class="kwd">new</span> HeavyProcess();
        <span class="kwd">public</span> MyDelegateExample()

        {

            <span class="cmt">//Create instance of delegate and give reference of method</span>
            dlgDBOperations dlgWeatherInfo = <span class="kwd">new</span> dlgDBOperations(hp.MakeScriptOfDatabase);
            <span class="cmt">//add another function reference</span>
            dlgWeatherInfo += <span class="kwd">new</span> dlgDBOperations(hp.ETW);
            <span class="cmt">//Calling all referenced method/function</span>
            dlgWeatherInfo();
            <span class="cmt">//remove function reference</span>
            dlgWeatherInfo += <span class="kwd">new</span> dlgDBOperations(hp.ETW);
            <span class="cmt">//Calling all referenced method/function</span>
            dlgWeatherInfo();
        }
    }
}

<o:p>

First of all, I would like to mention here one thing very important that these features are supported from .net 2.0. Delegates are type of safe function pointers but these are very flexible and are enough powerful to support Inheritance, isn’t it cool! J<o:p>

I didn’t mean here that you can make derived delegates, $ actually they support inheritance by means of return type and parameters type subclasses of the method to whom delegate refer. <o:p>

<o:p>

Covariance deals with return type of method whereas Contra variance deals with type of parameter(s).<o:p>

<o:p>

Covariance example

<span class="kwd">namespace</span> NSDelegate
{
    <span class="cmt">//super class</span>
    <span class="kwd">public class</span> Human { }
    <span class="cmt">//derive class by human</span>
    <span class="kwd">public class</span> Shemale : Human { }

    <span class="kwd">public class</span> MyDelegateExample
    {
        <span class="kwd">public delegate</span> Human MyDelegates();

        <span class="kwd">static void</span> Main()
        {
            <span class="cmt">//delegate pointing direct to its reference type</span>
            MyDelegates delg1 = GetHuman;
            <span class="cmt">//delegate pointing to subclass reference type</span>
            MyDelegates delg2 = GetShemale;
        }

        <span class="cmt">//instance method to create instance</span>

        <span class="kwd">public static</span> Human GetHuman()
        {
            <span class="kwd">return new</span> Human();
        }
        <span class="cmt">//instance method to create instance</span>

        <span class="kwd">public static</span> Shemale GetShemale()
        { 
            <span class="kwd">return new</span> Shemale();
        }
    }    
}

<o:p>

<o:p>

Contravariance Example

<span class="kwd">namespace</span> NSDelegate
{
    <span class="cmt">//super class</span>
    <span class="kwd">public class</span> Human { }
    <span class="cmt">//derive class by human</span>
    <span class="kwd">public class</span> Shemale : Human { }
    <span class="kwd">public class</span> MyDelegateExample
    {
        <span class="kwd">public delegate</span> Human MyDelegates();
        <span class="kwd">static void</span> Main()
        {

            <span class="cmt">//delegate pointing direct to its reference type</span>

            MyDelegates delg1 = GetHuman;

            <span class="cmt">//delegate pointing to subclass reference type</span>

            MyDelegates delg2 = GetShemale;
        }
        <span class="cmt">//instance method to create instance</span>

        <span class="kwd">public void</span>   GetHuman(Human hum)
        {
        }

        <span class="cmt">//instance method to create instance</span>
        <span class="kwd">public void</span> GetShemale(Shemale shem)
        { 
        }
    }    
}
 

Conclusion:<o:p>

<o:p>

Delegate is an object which can refer to method(s) and can call methods synchornously and asynchrously (by running methods on another threads). Using asynchornous delegates, we can call time taking processes of our application like emailing, database transactions, calling web services, File I/O operations. Also can run them on different threads which doesn’t freeze UI and user doesn’t need to wait a lot.<o:p>

<o:p>

Single Delegate can point to several methods of void return type and such kind of delegates are known as multicast delegates. <o:p>

<o:p>

Delegates are enough flexible to support inheritence means  which can accommodate derived class of return type and parameter(s) type of referenced method. These techniques are known as covariance and contravariance which were introduced in .net 2.0.

License

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


Written By
Software Developer (Senior) Candoerz
United Kingdom United Kingdom
trying to have can do attitude. Candoerz.com

Comments and Discussions

 
GeneralMy vote of 1 Pin
Todd Smith13-Jan-09 8:06
Todd Smith13-Jan-09 8:06 
GeneralUnderwhelming Pin
PIEBALDconsult13-Jan-09 7:53
mvePIEBALDconsult13-Jan-09 7:53 
GeneralMy vote of 2 Pin
#realJSOP13-Jan-09 6:40
mve#realJSOP13-Jan-09 6:40 

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.