January 6, 2014

Avanced CSharp Part 4 : Delegates and Events

New to C# ? Start from the beginning : Kick-Start C# : Your first program
Previous Post : Advanced CSharp Part 3 : params, ref, out and Preprocessors
Next Post : Exception Handling : The use of Try and Catch

This post is fairly advanced and interesting. Both of the topics are interrelated. You cannot learn events unless you learn delegates. So I thought I should probably put the two in the same post to show how relevant they are.

Delegates: Delegates are essentially call-back methods. You are probably familiar with call-back functions if you happen to come from Java or Javascript background. Call-back function is something that can determine your flow of code at run time. You can switch in and out using a call-back function. Delegates provide this functionality in C#.

To use delegates in C#, you have to keep in mind three basic steps -
  1. Define a delegate.
  2. Assign a delegate variable to a method of same signature as 1.
  3. Implement the method with the same signature as 1.
The following is a delegate program in action.

using System;

namespace Spells
{
    public delegate void NameFactory(string name);  // step 1 define
    class Program
    {
        public static void Main(string[] args)
        {
            NameFactory Namer = FirstLast;      // step 2 assign
            string myname = Console.ReadLine();
            int indexofcomma = myname.IndexOf(',', 0);
            if (indexofcomma > 0)
            {
                // user input in the form of Last name, First name
                Namer = LastFirst;   // step 2 assign
                Namer(myname);
            }
            else
            { 
                // user input in the form of Firstname Lastname
                Namer(myname);
            }
            Console.Read();
        }
        static void FirstLast(string name)   // step 3 implement
        {
            Console.WriteLine("Firstname Lastname format: {0}", name);
        }
        static void LastFirst(string name)   // step 3 implement
        {
            Console.WriteLine("Lastname, Firstname format: {0}", name);
        }
    }
}
Essentially a delegate provides you a framework, it tells you how certain methods must be implemented.
Observe line 5 in the program. The delegate keyword is needed to define a delegate. It looks like a method, but essentially it tells the compiler how certain methods must look like. The void keyword says that the method following this delegate will not return anything at all. Choose a name for your delegate and then choose the argument types.

Now look at line 26 and 30. Both the methods have the same signature as we see on line 5. They take a string parameter and return nothing. Inside the Main function, we assign these methods to the delegate. Notice line 10 how we assigned FirstLast method to a variable Namer of type NameFactory. In the perspective of this code, this is just a default assignment. You will see that this program decides at run time which method to call. If there is a comma in the input string, we can assume that the given name is of the type Last name, First name. So we re-assign the delegate to LastFirst at line 16. If there is no comma in the input string, we call the previously assigned delegate as in line 22.

Line 17 and 22 can give you the impression that you are indeed calling the same method. This is exactly the beauty of delegate. As for line 17, Namer is pointing to LastFirst method, while line 22 points to the FirstLast method. This is how delegate helps you to change the callback method on the fly.

Events: Events are important part of programming software that does intelligent things. Events are something like that of an agent. You appoint an agent to look after "something", and when "something" happens, your agent reports to you that "hey you have been looking for something! Now something happened, do something with it."

Lets take a look at a working example and then I will explain what's going on.

using System;

namespace Spells
{
    public delegate void MyEventHandler(string theString);   // step 1

    class ListenChanges
    {
        private string str;
        public event MyEventHandler ValueChanged;       // step 2

        public string MyString
        {
            set
            {
                str = value;
                this.ValueChanged(str);     // step 3
            }
        }
    }
    class Program
    {
        public static void Main(string[] args)
        {
            ListenChanges changes = new ListenChanges();
            //step 4
            changes.ValueChanged += changes_ValueChanged;   // subscribing to event
            while (true)
            {
                string val = Console.ReadLine();
                if (string.Equals(val, "exit", StringComparison.OrdinalIgnoreCase))
                {
                    break;
                }
                changes.MyString = val;    // this will trigger the event
            }
            Console.Read();
        }

        static void changes_ValueChanged(string theString)
        {
            Console.WriteLine("Event raised: current value : {0}", theString);
        }
    }
}
There are 4 steps involved in using events. I have commented out 4 steps in the code. You need to define a delegate, precisely to say a frame of the method that you want to call when something happens. Line 5 does exactly the same and its step 1 for us.

The class from line 7-20 is just an example demonstration. Observe line 10 where I have used the keyword event. The event have been named as ValueChanged and note that this event is following the delegate that I defined on line 5. MyString is a property and I have used the setter field to set a new value. Whenever I set a new value, I want to raise an event and say "Hey something changed!". At line 17, I call the ValueChanged callback method. Erase line 17 and write the same thing again. Once you put a dot [.] after this, you will see a lightning bolt in the drop down suggestion list.
Lightning bolt indicates an event
Then in the Main function, I create an object of the class ListenChanges. Go ahead and erase line 27 as well as the method on line 40 and try writing again. As you write changes[dot]ValueChanged +=, you will see a prompt from your Visual Studio editor that asks you to press Tab.
Pres Tab prompt
The += symbol means that you are subscribing to an event, just like you subscribe to a blog or a Facebook profile. Oppositely, the -= would mean that you are unsubscribing from the event. If you press Tab, the Visual Studio editor will prompt you to press Tab yet again.
Press Tab prompt 2
You may choose not to press Tab, and instead you may provide your own implementation. This is just a visual support from the IDE and its really helpful. You will discover a method as in line 40 after you press Tab again.

I have created an infinite loop at line 28 and I will keep on taking input from the console until I type the word "exit". At line 35 I set the property value with the current input from the console. This is how my output console looks like.
Output Console
What just happened? You see, whenever you set the MyString property at line 35, the event gets fired and essentially the line at 42 is printed to the console. Isn't that amazing? This is how events actually help you listen to certain things or changes and makes your code dynamic. You will find regular use of events when you code on Windows Forms, WPF, Windows Store Apps or Windows Phone 8.

I hope I have made your life easier with delegates and events. If yes, all credits goes to you. If no, then the burden is on me! Happy Coding!

No comments:

Post a Comment