Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do Events need Delegates? Why do we even Need Events?

Tags:

c#

winforms

wpf

I've been confused over the past weeks now about events. I understand how delegates work, not how it works in detail but enough to know that delegate datatype is a single cast delegate. delegate void is a multicast delegate - a list of references to methods.

I know a delegate type compiles to a class, but unfortunately I am still not sure how the method is referenced. For example

delegate void TestDelegate();
TestDelegate testDelegate = new TestDelegate(myObject.SomeMethod) ;

Question 1: I think myObject is the target, and SomeMethod is the method to reference, but I'm only passing one input. So is myObject.SomeMethod compiled to a string and is the string split by the period? Ridiculous I know.

Question 2: When you add to a multicast delegate

multicastdelegate+=newmethodtobereference
multicastdelegate() ;

Every method in the invocation list is called or notified? If that's true, why the hell do I need events or the event keyword? Is it simply to tell the developers that Hey, this is acting as an event? Because I'm seriously confused, I just want to move on at this stage lol. This is a sample code I wrote to test it today whether I need event keyword or not.

using System;
namespace LambdasETs
{
    public delegate void IsEvenNumberEventHandler(int numberThatIsEven);

    public class IsEvenNumberFound
    {
        public  IsEvenNumberEventHandler IsEvenNumberEvent;
        private int number;

        public void InputNumber(int n)
        {
            if(number %2 ==0)
            {
                if (IsEvenNumberEvent != null)
                {
                    IsEvenNumberEvent(n);
                }
            }
        }


        public static void Main()
        {
            IsEvenNumberFound isEvenNumberFound = new IsEvenNumberFound();

            isEvenNumberFound.IsEvenNumberEvent += IsEvenNumberAction;

             isEvenNumberFound.InputNumber(10);

            Console.ReadLine();

        }

        public static void IsEvenNumberAction(int number)
        {
            Console.WriteLine("{0} is an even number!", number);
        }
    }


}

Adding the event keyword to the field public IsEvenNumberEventHandler IsEvenNumberEvent; has no difference. Please can some explain so that a noob can understand thanks.

like image 780
Lews Therin Avatar asked May 27 '12 16:05

Lews Therin


2 Answers

An event is an accessor for a delegate, just like a property is an accessor for a field. With much the same goals, it prevents other code from messing with the delegate object. Like setting it null when a bunch of code you don't know about have subscribed a callback. An event restricts access to only adding and removing event handlers with the += and -= operators, external code cannot access the private delegate object at all.

And to customize the subscription with the add and remove accessors. You don't often do so because you are typically happy with the default accessors generated by the compiler. Including a hidden backing field that stores a delegate. But it is not uncommon in the framework code for example. Like all the event handlers for the many events that System.Windows.Forms.Control supports, they are all stored in a single EventHandlerList. Or the WPF equivalent, EventHandlersStore.

like image 100
Hans Passant Avatar answered Sep 25 '22 22:09

Hans Passant


but enough to know that delegate datatype is a single cast delegate. delegate void is a multicast delegate - a list of references to methods.

Not true. All "normal" delegates are multicast, even if they have a non void return type.

Question 1: I think myObject is the target, and SomeMethod is the method to reference, but I'm only passing one input. So is myObject.SomeMethod compiled to a string and is the string split by the period? Ridiculous I know.

No, myObject.SomeMethod is a method group. This way of delegate instance creation involves a bit of compiler magic.

multicastdelegate+=newmethodtobereference

If multicastdelegate is a normal delegate variable, this is equivalent to multicastdelegate = multicastdelegate + newmethodtobereference i.e. it creates a new delegate that calls several methods, and assigns it to multicastdelegate.


Now to your main question: What's the purpose of events?

Events have delegate types. They behave similarly to properties. Their purpose is encapsulation, in particular they only allow consumers to subscribe(+=) and unsubscribe(-=) but not to read the value of the event.

Properties are a combination of two methods: get and set.

Events are a combination of two public methods subscribe and unsubscribe, and in the case of a field-like event also something similar to a private getter.

like image 37
CodesInChaos Avatar answered Sep 22 '22 22:09

CodesInChaos