Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding delegates and Events in C# using a specific example

So I'm at the point of understanding events and delegates.

I overally understand the usage of delegates. The only thing that concerns me about delegates is whether a delegate can be configured to work with functions that are not related to events in any way... if yes, how do I write the logic for a delegate-defined function? (I guess such function doesn't really have much of a point to it, but it's good to know.)

As for events... I'm having a hard time understanding it. I get the idea that an event is a function that gets executed when something happens in the code. However, I don't get the process of creating an event. Partially.

For this question I'll use an answer by Gary Willoughby: https://stackoverflow.com/a/803528/1104766 It was posted on a question from which I tried to understand this whole subject.

What I didn't get in the example above:
MyObject.OnMaximum += new MyEventHandler(MaximumReached);
First, how can you create an instance of a delegate, and pass it only 1 variable when it requires 2? There must be something I'm missing...
The second thing about this line is that the new ...() instance is being added to the OnMaximum function that resides in MyObject which is an instance of MyClass - what exactly is OnMaximum if such thing can be done? It was never really defined too!

      if(OnMaximum != null) {
        OnMaximum(this, new MyEventArgs("You've entered " +
          value.ToString() +
          ", but the maximum is " +
          Maximum.ToString()));
      }

As for this part, OnMaximum is called but it's logic was never really defined anywhere in the code, so what could be the outcome? Obviously I'd guess it'd be the text "You've entered............." but my question is to be more specific, what really happens with the values the function/event receives?

I marked all of my questions in BOLD for clarity.

P.S, I know this question generally has been posted a few times.
Please note that this specific question refers to an answer written by another member and the questions asked here are specific to this example. That's why such answers can't really be found in google.
For the record though, I did search before I posted, and I did try to understand, but I guess examples are the best way for me to understand something especially when my knowledge of the English CS vocabulary is lacking.

like image 384
Asaf Avatar asked Feb 18 '23 00:02

Asaf


2 Answers

I think you may be suffering from an overdose of syntactic sugar!

You see, all an event is, is a delegate. Actually, to be honest, it's a collection of delegates that can possibly be null.

Let's take an example:

public class Alarm
{
    public delegate void AlarmEvent();

    // my secret stuff

    // raise it!
    public void Ring()
    {
        if(OnAlert != null)
           OnAlert();
    }

    public event AlarmEvent OnAlert;
}

All the event keyword gives us here, is the ability to add and remove listeners to that event...

Alarm a = new Alarm();
a.OnAlert += myevent;
a.OnAlert += myotherevent;

A delegate on the other hand, whilst working exactly like we have just described, works more analogously as a function pointer. Imagine an abstract renderer, I could make the class as such:

public abstract class Renderer
{
    protected abstract void RenderImpl();
}

This means, I am bound to deriving from that render. But what if that renderer took a delegate?

public abstract class Renderer
{
    public delegate void RenderDelegate();

    public Renderer(RenderDelegate) { /* ... */ }
}

We are now separating out composition.

What am I getting at? Is either better or not? In the case of events, I am allowing the public to become observers of my class. They can react. In the second case, I define a user-supplied delegate to perform a niche function, whilst I retain the majority of control.

Delegates and events are mostly the same thing - but it is the design choices we make that ascertains which one is appropriate.

To address your other points, you bring up a great example of events versus delegates. If we were to change the alarm class above, to allow the delegate to return true or false, then what happens?

We'd get several observers returning true, but who is right and how to we check them?

Down the single delegate route, however... "Render successful" or "Render failed". Changing this single delegate is not so much of an issue. We can predictably test whether our renderer did the job:

if(!delegate_->Invoke())
    fallBackCode();

We can't really do that with events. Well, not predictably.

To put it more simply, events are there when you want to broadcast something and let someone else do something on receipt of that event. The bomb went off... Run, hide, call the National Guard, turn off the oven, or duck and cover.

Delegates allow you to change your functionality without changing your model (delegates follow a signature!). Great example of a delegate, is when you call List<T>.Sort. That's a delegate. It has a signature.

But you can also use them for more advanced things, such as altering a Renderer class without resorting to interfaces, and being able to supply a user-defined "snippet". I guess the easiest analogy here would be owner-drawn controls in Win32. No need to override the whole class, no need to provide an interface and write a lot of code. Just change the bit that renders the item in the combo box. Delegates are great examples of how you might achieve that.

like image 68
Moo-Juice Avatar answered Feb 20 '23 12:02

Moo-Juice


The tutorials at MSDN will answer all your questions:

Delegates: http://msdn.microsoft.com/en-us/library/aa288459(v=vs.71).aspx

Events: http://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx

like image 28
user1610015 Avatar answered Feb 20 '23 14:02

user1610015