Delegates to Events a close look and practical use

Esensahoo
Posted by in C# category on for Intermediate level | Points: 250 | Views : 16548 red flag
Rating: 5 out of 5  
 2 vote(s)

This article describes basics about delegate and events and later shows how it can be used in project or real time scenario.

Introduction


In my last article I wrote about practical use of delegate , however the article was incomplete, you can find the article at the below url.

 

http://www.dotnetfunda.com/articles/article1107-practical-use-of-delegate-in-real-time-application-1-.aspx

 

This time I have spent some time to write a complete article on delegate to event with practical use. This article explains basics of delegate first with simple example  and then concentrates on how we can practically use event and delegate in a project . If you find any improvement/comment feel free to email me at esensahoo@gmail.com.

 

What is delegate ?

 

Ø  It defines  prototype for functions

Means delegate defines the signature/parameter types  and the return type for functions

Ex -  delegate void Print(string Name);

 

 

Why Delegate?

 

Ø  In C# every variable/data is associated to a type and has a value.Similarly Delegate is a type for methods/functions.

 

Ex:-

 

int i; -> i is a variable of type int
i = 10; -> i
represents a value 10

Print p; -p is a variable of type Print

p = new Print(PrintHi); - p represents function PrintHi

 

off course we have to define the function PrintHi with same signature as delegate Print.

void PrintHi(string name)

        {

            Console.WriteLine("Hi.."+name);

        }

Now both PrintHi("John"); and p("John"); will give same output “Hi.. John”

 

Ø  Delegate being a method type enables us to set a concrete method as a property or pass a concrete method as a parameter like other type variables.

Ex:

class X

    {

        public int p;

        public void writeTriple(int q)

        {

            Console.WriteLine(q*3);

        }

    }

X o = new X();

o.p = 10;

int q=5;

o.writeTriple(q);

 

class X

    {

        public Print p;

        public void SayHi(Print q)

        {

            q("John");

        }

    }

X o = new X();

o.p = new Print(PrintHi);

Print q = new Print(PrintHi);

o.SayHi(q);

 

 

Show me a complete program on Delegate?

 

//Step-1  Declare a delegate

delegate void Print(string Name);

 

//Step-2 Define a method for delegate having same signature

void PrintHi(string name)

    {

       Console.WriteLine("Hi.."+name);

    }

 

//Step-3 Create an instance of delegate by associating concrete method

 Print p = new Print(PrintHi);

 

//Step-4 Invoke the delegate

  p("John");

 

Putting all the steps together in a program:

 

class Program

    {

        //Step-1  Declare a delegate

        delegate void Print(string Name);

 

        //Step-2 Define a method for delegate having same signature

        static void PrintHi(string name)

        {

            Console.WriteLine("Hi.." + name);

        }

        static void Main(string[] args)

        {

            //Step-3 Create an instance of delegate by associating concrete method

            Print p = new Print(PrintHi);

 

            //Invoke the delegate

            p("John");

        }

    }

 

Output Will be “Hi..John” as shown below


 

 

What is multi casting in Delegate?


Ø  Associating multiple functions to a delegate instance is called multicasting

Ø  In multicasting single invoke on the delegate instance executes all the functions in the order they are associated with the delegate instance.

Ex:

    class Program

    {

        delegate void Print(string Name);

        static void PrintHi(string name)

        {

            Console.WriteLine("Hi.." + name);

        }

        static void PrintBye(string name)

        {

            Console.WriteLine("Bye.." + name);

        }

        static void Main(string[] args)

        {

            //Associating multiple methods to delegate instance

            Print p = new Print(PrintHi);

            p += new Print(PrintBye);

 

            p("John");

 

}

    }

Output :


 

 

What is Anonymous method in delegate? Or  What is inline delegate declaration?

 

Associating the method body in line with the delegate instance instead of using named methods.

Ex:

class Program

    {

        delegate void Print(string Name);      

        static void Main(string[] args)

        {

            //Defining the methid body inline

            Print p = delegate(string name) { Console.WriteLine("Hi.." + name); };

            p("John");

            Console.Read();

        }

    }

Output will be same “Hi..John”.

 

Give me a scenario where I can use delegate?

 

In the below example I have shown a User class. Client will use this class to create and register a user , however it entirely depends on the client  to implement how they want to notify users about their registration userid and PIN via email or via SMS.

 

    namespace RegistrationModule

    {

        public delegate void NotifyUser(ContactDetail objContact,string Notification);               

        public class User

        {

            public string Name;

            public int Age;

            public ContactDetail Contact=new ContactDetail();

            public NotifyUser Notify;

            public void Register()

            {

                //code to save the user details to the database

                // and generate userID

                string userID=(new Random()).Next(1111,5555).ToString();

                Console.WriteLine("User details saved to database.");

                Notify(Contact,"Registred Successfully,Your UserID is:"+userID);

                //Code to generate random 4 digit T-pin

                string PIN=(new Random()).Next(5555,9999).ToString();

                Notify(Contact, "Your PIN is " + PIN);

            }

        }

        public class ContactDetail

        {

            public string Email;

            public string MobNo;

        }

    }


Lets say first client wants to send SMS to notify their user.So below will be their implementation.

I have given the comment to explain the code.

class Program

    {

        static void Main(string[] args)

        {

            User usr = new User();

            usr.Name = "satya";

            usr.Age = 29;

            usr.Contact.Email = "satya@test.com";

            usr.Contact.MobNo = "997766553";

            usr.Notify = new NotifyUser(SendSMS);

            usr.Register();

 

            Console.Read();

        }

 

        //Below function is having same signature as delegate NotifyUser and will be attached to the delegate.

        static void SendSMS(ContactDetail objContact,string NotificationMsg)

        {

            string MobNo = objContact.MobNo;

            //Add your code to send NotificationMsg to the user mobile number.

            Console.WriteLine("SMS Sent to" + MobNo);

        }

     }


OutPut:


 

Now lets say the second client wants to notify the user via email: 

 

class Program

    {

        static void Main(string[] args)

        {

            User usr = new User();

            usr.Name = "satya";

            usr.Age = 29;

            usr.Contact.Email = "satya@test.com";

            usr.Contact.MobNo = "997766553";

            usr.Notify = new NotifyUser(SendEmail);

            usr.Register();

 

            Console.Read();

        }

 

 

        //Below function is having same signature as delegate NotifyUser and will be attached to the delegate.

        static void SendEmail(ContactDetail objContact, string NotificationMsg)

        {

            string email = objContact.Email;

            //Add your code to send NotificationMsg to the user email.

            Console.WriteLine("email Sent to" + email);

        }    

   }

 

That's it. Now client-1 user will get userid and password via SMS and client-2 will get userid and password via  email.  Important thing to notice here is SendSMS and SendEmail is the code written by the client however it is invoked by the User class what in other words we can say delegates allow us to inject functionality.

  

Show me a scenario where I can use multi-casting ?

 

In the above scenario let’s say the client wants to send the notification both via email and SMS, well below is the simple change he has to make.

 

usr.Notify = new NotifyUser(SendSMS);

usr.Notify += new NotifyUser(SendEmail);

usr.Register();

 

What is an Event?

 

Ø  Event provides a way for objects to notify state change or any action.

Ø  Technically events are delegate instance declared with event keyword.

Ex :


delegate void Print();

event Print OnStartPrint;

 

 

Why Events? Can not delegate do the same thing?

 

Yes delegate can do the same thing, but does not give abstraction. Means client can invoke the delegate where ever they want ,but event won’t allow that.

 

Show me a practical example showing difference between event and delegate?

 

Let’s consider our above example of user registration.

 

class Program

    {

        static void Main(string[] args)

        {

            User usr = new User();

            usr.Name = "satya";

            usr.Age = 29;

            usr.Contact.Email = "satya@test.com";

            usr.Contact.MobNo = "997766553";

            usr.Notify = new NotifyUser(SendEmail);

            usr.Register();

 

            Console.Read();

        }

       

        static void SendEmail(ContactDetail objContact, string NotificationMsg)

        {

            string email = objContact.Email;

            //Add your code to send NotificationMsg to the user email.

            Console.WriteLine("email Sent to" + email);

        }    

   }

 

Looks good with delegate ,  but what if the client uses the below code.

 

class Program

    {

        static void Main(string[] args)

        {

            User usr = new User();

            usr.Name = "satya";

            usr.Age = 29;

            usr.Contact.Email = "satya@test.com";

            usr.Contact.MobNo = "997766553";

usr.Notify = new NotifyUser(SendEmail);

usr.Notify(usr.Contact, "Your TPIN is 1234");

            //usr.Register();

            Console.Read();

        }

 

 

       

        static void SendEmail(ContactDetail objContact, string NotificationMsg)

        {

            string email = objContact.Email;

            //Add your code to send NotificationMsg to the user email.

            Console.WriteLine("email Sent to" + email);

        }    

   }

 

Output:



Now the SMS  is sent even though the user  is not registered.

 So now a question, should we allow the client to write the below line of code, ie should we give access to him to invoke the delegate?

usr.Notify(usr.Contact, "Your TPIN is 1234");

Off course NO,  in our case because only User.Register() method knows when userid  is created and when password is created ,so no one other than User class should be allowed to invoke the delegate.

 

So how do we fix this problem...simple use event. By declaring the Notify as event user will get compilation error if he attempts to invoke the event by below line

 

usr.Notify(usr.Contact, "Your TPIN is 1234");

 

So what changes we have to make in our program?

 

1.       Just add the event keyword before the delegate name NotifyUser in the RegistrationModule.User class as below.

 

      public event NotifyUser Notify;

 

2.       Use  +=  instead of  =  for initializing events i.e

 

usr.Notify += new NotifyUser(SendEmail);

 

 

Show me the Complete Program ?

 

    namespace RegistrationModule

    {

        public delegate void NotifyUser(ContactDetail objContact,string Notification);               

        public class User

        {

            public string Name;

            public int Age;

            public ContactDetail Contact=new ContactDetail();

            public event NotifyUser Notify;

            public void Register()

            {

                //code to save the user details to the database

                // and generate userID

                string userID=(new Random()).Next(1111,5555).ToString();

                Console.WriteLine("User details saved to database.");

                Notify(Contact,"Registred Successfully,Your UserID is:"+userID);

                //Code to generate random 4 digit T-pin

                string PIN=(new Random()).Next(5555,9999).ToString();

                Notify(Contact, "Your PIN is " + PIN);

            }

        }

        public class ContactDetail

        {

            public string Email;

            public string MobNo;

        }

    }

    class Program

    {

       

        static void Main(string[] args)

        {

            User usr = new User();

            usr.Name = "satya";

            usr.Age = 29;

            usr.Contact.Email = "satya@test.com";

            usr.Contact.MobNo = "997766553";

            usr.Notify += new NotifyUser(SendEmail);

            usr.Register();

 

            Console.Read();

        }

 

        static void SendEmail(ContactDetail objContact, string NotificationMsg)

        {

            string email = objContact.Email;

            //Add your code to send NotificationMsg to the user email.

            Console.WriteLine("email Sent to" + email);

        }

    }

 

Output:

  

 

Can we make the program better in a industry standard way?

 

We practically exposed an event and handled it. But it’s not a industry standard way or recommended way.

So how can we make it better?..just by using System.EventHandler delegate.

 

Show me the complete program?

   

 

namespace RegistrationModule

    {

        public class User

        {

            public string Name;

            public int Age;

            public ContactDetail Contact=new ContactDetail();

            public event EventHandler<NotiFyEventArgs> Notify;

            public void Register()

            {

                //code to save the user details to the database

                // and generate userID

                string userID=(new Random()).Next(1111,5555).ToString();

                Console.WriteLine("User details saved to database.");

                NotiFyEventArgs args = new NotiFyEventArgs();

                args.Contact = Contact;

                args.NotificationMsg = "Registred Successfully,Your UserID is:" + userID;

                Notify(null,args);

                //Code to generate random 4 digit T-pin

                string PIN=(new Random()).Next(5555,9999).ToString();

                args.NotificationMsg = "Your PIN is " + PIN;

                Notify(null,args);

            }

        }

        public class ContactDetail

        {

            public string Email;

            public string MobNo;

        }

 

        public class NotiFyEventArgs : EventArgs

        {

            public ContactDetail Contact;

            public string NotificationMsg;

        }

    }

 

    class Program

    {

       

        static void Main(string[] args)

        {

            User usr = new User();

            usr.Name = "satya";

            usr.Age = 29;

            usr.Contact.Email = "satya@test.com";

            usr.Contact.MobNo = "997766553";

            usr.Notify += new EventHandler<NotiFyEventArgs>(SendSMS);

            usr.Register();

 

            Console.Read();

        }

 

 

        

static void SendSMS(object o,NotiFyEventArgs args)

        {

            string MobNo = args.Contact.MobNo;

            //Add your code to send NotificationMsg to the user mobile number.

            Console.WriteLine("SMS Sent to" + MobNo);

        }

    

}

OutPut:


 

Are we done??

 

Yes almost, just one more recommendation, use On before event .Say for example in our case we can name our event as OnRegistration instead of Notify.But I have kept it Notify just to keep the naming same, so that there will be less change between programs.

I hope this article will be useful. Appreciate if you can by responding to this article.

Page copy protected against web site content infringement by Copyscape

About the Author

Esensahoo
Full Name: SATYA SAHOO
Member Level: Starter
Member Status: Member
Member Since: 12/28/2010 8:47:18 AM
Country: India


Working in Misys Software solution having interest in learning and writing on MS.Net technologies.

Login to vote for this post.

Comments or Responses

Posted by: Karam on: 7/18/2011 | Points: 25
Really good job................
Posted by: Hiren009 on: 7/25/2011 | Points: 25
Thanks for article
Posted by: A4u_6178 on: 7/25/2011 | Points: 25
Hello SATYA SAHOO,
Nice article.....
5 from me....

Login to post response

Comment using Facebook(Author doesn't get notification)