1

I am new to events and I am trying to see how an event works and what purpose they would have. The code below is some code that a friend helped me with that we found on the net. It works but I am not certain as to how the event is used.

In the Main method there is the EventTest which creates a new object e which then intern calls SetValue method twice with a different parameter.

static void Main(string[] args)
{
    EventTest e = new EventTest(5);
    e.SetValue(7);
    e.SetValue(11);
    Console.ReadKey();
}

The following code is actually the event code.The OnNumChanged is the event that writes information if the number is changed. So when SetValue(100) is set to a different number then the event is fired.

Question: When the SetValue is set with a new value this is what cause the event to change correct?

I am just new enough to the event change that I could really use some good examples or have someone really explain this example line by line.

e.SetValue(7);
e.SetValue(11);

protected virtual void OnNumChanged()
{
     if (ChangeNum != null)
     {
          ChangeNum();
     }
     else
     {
          Console.WriteLine("Event fired!");
     }
}

Code:

class Program
{
    static void Main(string[] args)
    {
        EventTest e = new EventTest(5);
        e.SetValue(7);
        e.SetValue(11);
        Console.ReadKey();
    }
}

public class EventTest
{
    private int          value;
    public delegate void NumManipulationHandler();
    public event         NumManipulationHandler ChangeNum;

    public EventTest(int n)
    {
        SetValue(n);
    }

    public void SetValue(int n)
    {
        if (value != n)
        {
            value = n;
            OnNumChanged();
        }
    }

    protected virtual void OnNumChanged()
    {
        if (ChangeNum != null)
        {
            ChangeNum();
        }
        else
        {
            Console.WriteLine("Event fired!");
        }
    }
}
Christoph Fink
  • 22,727
  • 9
  • 68
  • 113

2 Answers2

0

Yes, you are correct:

public void SetValue(int n)
{
    if (value != n) // check if the value actually changed
    {
        value = n;
        OnNumChanged(); // call the event "in a save way", see below
    }
}

protected virtual void OnNumChanged()
{
    if (ChangeNum != null) // check if someone is listening - PROBLEM: see below
        ChangeNum(); // trigger the event and call all event handlers registered
}

The Problem I mentioned above: You get the event to check it for null and then get it again to execute. In a multi-threaded environment it can happen, that between these two "gets" it changes => create a local copy:

protected virtual void OnNumChanged()
{
    var changeNum = ChangeNum;
    if (changeNum != null)
        changeNum();
}

To actually get notified on the event you need to register for the event e.g. like this:

static void Main(string[] args)
{
    EventTest e = new EventTest(5);
    e.ChangeNum += () => Console.WriteLine("Num changed"); //<== this
    e.SetValue(7);
    e.SetValue(11);
    Console.ReadKey();
}

It also would make more sense to also supply the new value in the event. That can be done by altering the delegate to:

public delegate void NumManipulationHandler(int newValue);

and call it like:

ChangeNum(value);

Then you can register like:

e.ChangeNum += newValue => Console.WriteLine("Num changed to " + newValue);
Christoph Fink
  • 22,727
  • 9
  • 68
  • 113
  • Is that really the only purpose of an event to see if the value changes. If ChangeNum is not null then call ChangeNum but isn't ChangeNum a delegate with a void return type and no parameters which is OnNumChanged(). I guess I am still not certain to as how a event would be used. Because in this example "Event fired!" is fired when the ChangeNum != null. –  Apr 23 '14 at 13:40
  • Does the else in OnNumChanged need to be there. –  Apr 23 '14 at 13:59
  • var changeNum = ChangeNum; ---- Is this code really needed because it will work with just having ChnageNum. I do understand it better however. –  Apr 23 '14 at 14:01
  • As already said in the post: `ChangeNum` could become `null` after you check for it in a multi-threaded environemnt, so you should always do this local copy. I for myself created a helper extension doing this so I can simply call `ChangeNum.Raise(...)` from anywhere I want... – Christoph Fink Apr 23 '14 at 14:11
  • Hate to ask but could you put your helper Raise(...) method in your code above. It would help to see it and for latter post reference it would be god. –  Apr 23 '14 at 14:15
  • I added it as a own question+answer, as it is possible usefull to others also: http://stackoverflow.com/questions/23247384/how-to-get-rid-of-event-firing-boiler-plate-code/23247385#23247385 – Christoph Fink Apr 23 '14 at 14:29
0

in short: yes! if the value that is passed along with the SetValue method differs from the one that was already stored, an event is fired, indicating the change as such.

Any other code that might be subscribed to such an event can then react accordingly in whatever way.

Even though I myself can learn easier from video (and I advise you to search for videos on events in C# as well), it all boils down to a way for a class to provide notifications to clients of that class when some interesting thing happens to an object (further reading here)

Wim Ombelets
  • 5,097
  • 3
  • 39
  • 55