The documentation for EventHandler<TEventArgs>
says:
The second parameter is a type derived from EventArgs and supplies any fields or properties needed to hold the event data.
and it seems to be generally recommended throughout the .Net documentation.
However it turns out that I can do the following which works just fine:
public event EventHandler<int> Panned;
and invoke the event handler as:
int value = 10;
if (Panned != null)
{
Panned(this, value);
}
and on the observer side:
subject.Panned += (sender, e) =>
{
Console.WriteLine(e);
};
To me this seems better than littering the code with little classes that inherit from EventArgs
or having a generic EventArgs
as proposed by Does .NET have a built-in EventArgs<T>?
So why is it required that I inherit the EventHandler
generic argument from EventArgs
?
If all you need to do is pass an int
to the handler then what you are doing is fine.
It used to be the case (before .NET 4.5) that the EventHandler
type argument TEventArgs
was constrained to inherit from EventArgs
but not anymore:
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
The fact that MS dropped the constraint should tell you that they were being too strict and what you are doing is fine.
In the case that you need to pass a complex type to the handler then you might aswell inherit EventArgs
for reasons of polymorphism. Also, the EventArgs.Empty
member is useful.
This is just a convention. In fact, you don't even have to use the EventHandler<>
generic delegate. You could have:
public event Action SomeEvent;
public void OnAction()
{
var a = this.SomeEvent;
if (a != null)
{
a();
}
}
Of course, the convention is there for a reason. As far as I know, every standard .NET event follows the pattern of using a void-returning delegate that takes an object
parameter and a second parameter of EventArgs
or a derived type. This makes it easy to use these events without having to refer to the documentation each time.
Will this work?...
class Program
{
public static event Func<int> SomeEvent;
static void Main(string[] args)
{
SomeEvent += () => 7;
SomeEvent += () => 8;
var a = SomeEvent();
Console.WriteLine(a);
}
}
I tried it: it does! Of course, it's very odd to have an event where the delegate has a return value, because it's not obvious which handler's value will be returned to the caller if there are multiple attached handlers. In the above example, it turns out that 8
is written to the console.
Interesting but, I suspect, useless ;-)
I don't think it would ever be sensible to have a non-void returning delegate type, as in my example. However, you might consider using a delegate whose parameters are value types (structs, not classes) for performance reasons. It might be possible to use events without incurring the garbage collection penalty of allocating EventArgs
objects on the heap.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With