10

I'm learning events in C# and understand that the EventArgs class carries data about the event. But I am having difficulties understanding why EventArgs is necessary.

For instance, in this MSDN example, couldn't the WakeMeUp class read all of the necessary data (snoozePressed, nrings) from the fields of AlarmClock? If it can set them, why couldn't it also get them?

6 Answers 6

11

The upsides with the EventArgs class are (as I see it) mainly these two:

  • You can add members to the EventArgs class withouth altering the signature of the event
  • You disconnect the information passed to the event handler from the object instance

It may even be that the information contained in the EventArgs is not exposed by the object raising the event.

Sure, in some cases it may seem like overkill, but I think that the power of sameness is a good thing here; if you know how one event works, you know how other events work as well.

1
  • 1
    The event args is a great way to let the subscriber know what the prior value of a given property was for a property changed event, assuming that such information might be useful.
    – Greg D
    Commented Jul 17, 2009 at 12:30
9

The EventArgs class is necessary because if you wanted to extend your event to provide more information in the future, you would have portability problems for all clients using the original method signature of the original event.

For example,

public void IHandleEventVersion1(string p1, int p2)
{
    ....
}

Now you want to provide more information in event EventVersion1 above (you want to include a char). You would then have to force the client rewrite their event handling to to match your new requirements like so:

public void IHandleEventVersion1(string p1, int p2, char p2)
{
    ...
}

See how awkward it could become when trying to provide more information?

So, the EventArgs class provides a common design pattern to programme against, allowing you and me to quickly extend the data we want to provide for an event.

The general coding pattern of the eventing framework is such:

Basic event handling strategy

  1. Define an event that consumers of your class can subscribe to
  2. Define a delegate signature that the event declares (yes, you can also use the .NET 2.0 generic version of EventHandler, namely, EventHandler<TEventArgs>)
  3. Provide a protected virtual method for inheritors to override in response to the event being raised in your base class
  4. In the base class that declares your event, provide a base implementation of the protected method where you actually raise the event.

    public class MyClass
    {
        public event EventHandler  /* (point 2) */ MyEvent; /* (point 1) */
    
        // (point 3 + 4)
        protected virtual void OnMyEvent()
        {
            EventHandler temp = MyEvent;
            if (temp != null)
                temp(this, EventArgs.Empty);
        }
    
        public void SomeMethodThatWillRaiseTheEvent()
        {
            ....
            OnMyEvent();
        }
    }
    
6

EventArgs is useful for:

  • showing you the state at the point in time at which the event happened
  • improving the performance of your event handling code by providing the information regarding the event without you needing to query a "3rd party"
  • containing data that isn't exposed by the object raising the event

To expand on the first point.... in-between your event handler being called and you reading state out of the object that raised the event, other things could've happened which changed the state to something else entirely. In that circumstance, you'd be responding to for example, an "AlarmHasGoneOff" event on an AlarmClock where the alarm has already been switched off.

It's also possible to respond to events that have been raised "elsewhere" - be that in another process/appdomain/process on another machine through various different mechanisms. If you then had to call back into that "elsewhere" to get the information you required, that could take several seconds (or less, or more!), making the passing of useful/required data through EventArgs or a derived class a massive performance improvement.

1
  • +1 State at the point in time. Especially for threadsafe code.
    – jnm2
    Commented Feb 25, 2014 at 13:02
2

The data passed in EventArgs isn't necessarily available in properties of the object that generated the event. For instance, on a MouseDown event, the MouseEventArgs includes information on the current mouse position. The object that generated that event probably doesn't even store anything so volatile.

2
  • This makes sense. But is it necessary in this sample?
    – Daar
    Commented Jul 17, 2009 at 8:57
  • Yes. Even if you could get at the data another way, if it's to follow the pattern of every other .NET event, then the EventArgs should carry the data pertaining to the event. Commented Jul 17, 2009 at 9:02
2

You don't have to pass EventArgs.Empty to the handler. You can pass any derived class. When an event handler is specified to take EventArgs as a parameter, it means there are no specific arguments that are always available, but you might want to pass your own for extra information.

1

Another nice thing you get from following the standard pattern is that people using your class that provides the event can hook up common event handlers:

public SomeWinFormClass() { 
  InitializeComponent();
  _yourClassInstance = new YourClass();
  someButton.Click += SomethingICareAboutHappened;
  _yourClassInstance.YourEvent += SomethingICareAboutHappened;
}

private void SomethingICareAboutHappened(object sender, EventArgs e)
{
  // do something -- logging, signaling a handle someone's 
  // waiting for, etc.
}

Not having to declare all your own custom delegates to declare your events is nice, as well. If you used EventHandler<TEventArgs> to declare YourEvent, I don't think you can get away with this, though it seems like you should be able to.

Not the answer you're looking for? Browse other questions tagged or ask your own question.