Pranay Rana: March 2016

Sunday, March 20, 2016

Event Vs Deleagte

Post is explains basics of Events & Delegate and most importantly explains what is difference between both.
Both Event & Delegate is based on overserved pattern of GOF, which is based on giving notification of change in one thing (object) to all others who is interested in change. Below image is graphical interpretation of same.



Delegates
Delegate in C# is reference type, which hold reference to the function and invokes function when called with Invoke method. If one is coming from C++/C background, delegate is like pointer to function which points to function.
To understand delegate better way have look to below sample code.

    public class DelegateTest
    {
        public delegate void Print(string val);

        public DelegateTest()
        {
            Print p = new Print(PrintValue);
            p += new Print(PrintData);
            p.Invoke("Test");
        }

        private void PrintData(string s)
        {
            Console.WriteLine("PrintData" + s);
        }

        public void PrintValue(string s)
        {
            Console.WriteLine("PrintValue" + s);
        }
    }

When above class get invoked following output will get printed
PrintData Test
PrintValue Test

Key points in above code
  1. It defines delegate which can points to method with void return type and take string as input
  2. In constructor of type, it create reference object of delegate which points to method “PrintData” and “PrintValue”.
  3. Invoke method of delegate calls both methods one by one
Read more about Delegate : https://msdn.microsoft.com/en-in/library/900fyy8e(v=vs.71).aspx

Events
Event in C# is of type Delegate, which means that if one wants to use event than one must need to define delegate first. Event can have multiple event-handler functions which are of signature like delegate which get called when event raised by some event in application Simple Example is Button click on UI. Event is very useful to create notification.
To understand delegate better way have look to below sample code.

    public class EventTest
    {
        public delegate void Print(string val);
        public event Print PrintEvent;

        public EventTest()
        {
            this.PrintEvent +=  PrintData;
            this.PrintEvent += PrintValue;
        }

        public virtual void OnPrintEvent()
        {
            if (PrintEvent != null)
                PrintEvent("Test");
        }

        private void PrintData(string s)
        {
            Console.WriteLine("PrintData" + s);
        }

        public void PrintValue(string s)
        {
            Console.WriteLine("PrintValue" + s);
        }
    }

When above class object is created and then “OnPrintEvent” method invoked following output will get printed
PrintData Test
PrintValue Test

Key points in above code
  1. Its creates delegate which can point to method with return type void and take string as argument
  2. It defines Event which is of type defined delegate
  3. In Constructor, event holds two delegate i.e. Event handlers. It can also be written like
  4.           this.PrintEvent += new Print (PrintData);
              this.PrintEvent += new Print (PrintValue);
    
  5. OnPrintEvent method checks event is holding event handler function or not, if there is any event handler(s) it calls all event handlers.
Read more about Event : https://msdn.microsoft.com/en-in/library/8627sbea%28v=vs.71%29.aspx

Event VS Delegate
Both event and delegate does the same task, which is hold event handlers and call them when delegate/event invoked. So one always has question, what is need of Event in language C# when one can achieve same thing with Delegate.

Answer is Event is wrapper on Delegate type.

Problem With Delegate
Let’s understand this, using same class defined above which is “DelegateTest”.
    class Program
    {

        static void Main(string[] args)
        {
            Program p = new Program();
            DelegateTest delegateTest = new DelegateTest();
            delegateTest.p = new DelegateTest.Print(p.TestString);
            delegateTest.p = null;
        }

        public void TestString(string s)
        {
        }
    }
Above doe does following things
  1. It creates object of type DelegateTest
  2. Its assigns new delegate reference to delegate Print and override value assigned in constructor
  3. Its assigns “null” to Print delegate and removes all added function.

Problem with Delegate is that one can easily override delegate property and that lead to error or serious issue. That means one cannot use delegate as public property.

Solution with Event
To avoid above problem C# has Events, Which defines wrapper around delegate. (Below code make use of EventTest class defined above and as form above code PrintEvent is wrapper around Print delegate).
static void Main(string[] args)
        {
            Program p = new Program();
            EventTest eventTest = new EventTest();
            //eventTest.PrintEvent = null;//Not allowed in C#
            eventTest.PrintEvent += p.TestString;
        }

        public void TestString(string s)
        {
        }
Above does following things
  1. It defines object of type EventTest
  2. its assigns eventhandler to PrintEvent event of EventTest
One cannot do below things with Event
	eventTest.PrintEvent = null;//Not allowed in C#
	eventTest.PrintEvent = new PrintEvent()//Not allowed in C#

So Event type resolve problem of exposing delegate outside class by defining wrapper around delegate. Below image is presentation of Event & Delegate.



Another Difference between Event & Delegate is
  1. Event is very helpful to create Notification system. Same is not possible with delegate because delegate cannot be exposed as public.
  2. Delegate is very helpful to create call back function i.e can pass delegate as function argument, which is not possible with Event.
Conclusion
Event and Delegate are both follows Observer pattern. Difference between both is Event wraps Delegate type and which makes delegate not modifiable in terms of changing reference i.e. assign new object is not possible.