2

I want to ask the different between EventHandler and EventHandler<T>.

Previously I have implemented a EventHandler, with a custom EventArgs which can be passed to the parent page from the user control.

I thought I need to apply EventHandler< T >, however it can be implemented by using EventHandler. (in fact there is weird error when I trying to apply EventHandler<T>, the program is worked but error is shown in the IDE which I couldn't solve [C# Custom EventHandler ])

Thus, I want to know in what situation I need to apply EventHandler < T > ?

public event EventHandler AppendProcess;
public event EventHandler<MyEventArg> AppendProcess;

---Update--- this is how I invoke the event in the user control (as i said, i can pass object to parent page by doing this (although i don't know if it is correct to do so)

if (AppendProcess == null) { }
else
    AppendProcess(this, new Common.WinLose_ProgressStage(Common.WinLose_SP_Parameter.upper, displayLevel + 1, 
                                                            (int)Common.WinLose_Level.lvChild4, thename, refundratio, 
                                                            selfproportion, -1, -1, loadlevel, isPlayer, betsource, gamecategory, false));
Community
  • 1
  • 1
SKLTFZ
  • 841
  • 2
  • 10
  • 30
  • with `EventHandler` you can pass parameter of type `T` to subscribers. with `EventHandler` you cant pass any parameters (i.e just `EventArgs.Empty` which is useless) – M.kazem Akhgary Dec 20 '16 at 09:48
  • 2
    @M.kazemAkhgary You can (and the OP does) pass in concrete classes derived from `EventArgs`, and you can (and the OP does) cast the parameter to the concrete class type inside the handler. I certainly don't recommend it, but saying "you can't" after the OP has already shown you can doesn't help. –  Dec 20 '16 at 09:54

3 Answers3

8

EventHandler<T> is just a generic EventHandler type, which avoids you having to declare a new delegate type for each kind of EventArgs you want to use.

Consider Control.KeyPress for example. It's declared as an event of type KeyPressEventHandler. That delegate is just declared as:

public delegate void KeyPressEventHandler(object sender, KeyPressEventArgs e)

If EventHandler<T> (and generics) had been around when that was created, the event could have been declared as an EventHandler<KeyPressEventArgs> instead, saving a delegate declaration. There are many, many delegates which are just like EventHandler, and only vary in the type of the second parameter - EventHandler<T> avoids that redundancy.

No if you don't have your own custom EventArgs subclass, there's no reason to use EventHandler<T>... but if you do, it's much better to use it, so that the method handling the event receives your custom EventArgs subclass in a strongly-typed way.

As an aside, your way of invoking the event handler isn't thread-safe. Another thread could unsubscribe the final event handler after your nullity check. If you're using C# 5, you should write it as:

var handler = AppendProcess;
if (handler != null)
{
    handler(this, new Common.WinLose_ProgressStage(...));
}

If you're using C# 6 or later, you can use the null conditional operator:

// If AppendProcess is null, the arguments won't even be evaluated
AppendProcess?.Invoke(this, new Common.WinLose_ProgressStage(...));
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I get the impression this answers a question the OP didn't ask, and avoids answering the question the OP did ask. The OP isn't asking about `EventHandler` vs. `KeyPressEventHandler`, the OP is asking about `EventHandler` vs. `EventHandler`. –  Dec 20 '16 at 09:56
  • @hvd: Will edit to clarify. (Although I'd say it answers the question asked in the first sentence...) – Jon Skeet Dec 20 '16 at 09:57
  • ok, so EventHandler< T > is just like a strong typed parameters of function. and the main different between Eventhandler and Normal function is that the EventHandler has to in the format of (object, EventArgs), in this case when I wanted to define the strongly typed EventArgs in order to prevent invalid invoke from user control, I need to apply EventHandler< T> . I think i have more understand on EventHandler now. Thanks – SKLTFZ Dec 20 '16 at 10:26
  • @SKLTFZ: I don't know what you mean by "normal function" but you should probably read up on delegates more. And strongly typed event args are useful in the same way that strong static typing is useful everywhere... – Jon Skeet Dec 20 '16 at 10:29
  • they(normal function...) properly called method in C#! ya, still finding more information for EventHandler and Delegates, thanks. – SKLTFZ Dec 20 '16 at 10:35
4

EventHandler<T> is the generic variant of EventHandler. Usually, you would override EventArgs and EventHandler to come up with an own event type. You still need to derive EventArgs if you want to pass in custom properties to the e argument, but you don't need to create a custom delegate for EventHandler any more. You now can just say:

public event EventHandler<SomeEventArgs> SomeEvent;

Which is more convenient than:

public delegate void SomeEventHandler(object sender, SomeEventArgs e);

public event SomeEventHandler SomeEvent;

When your delegate signature doesn't change, EventHandler<T> is much more straightforward to use.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • 1
    And of course EventArgs can be derived with a EventArgs to get rid hassle of creating custom classes for every type! – J.R. Dec 20 '16 at 10:04
  • 1
    @J.R. `EventArgs` is not a standard type though. It can be an option if you've already got some library that defines it, but if not, then you need to create a custom class either way. –  Dec 20 '16 at 10:12
  • i have found the similar information too in my previous digging! thanks for clarification – SKLTFZ Dec 20 '16 at 10:19
2

From your other question:

Common.WinLose_ProgressStage wps = (Common.WinLose_ProgressStage)e;

That's a cast that could potentially fail, depending on how the method is invoked. There is nothing guaranteeing that your event handler only gets called with Common.WinLose_ProgressStage that can be inspected without checking your full program. It could be called with a plain EventArgs too: you made that possible by making the parameter type EventArgs.

EventHandler<T> causes more compile-time type checking. If other code attempts to pass in EventArgs.Empty, the call would simply fail to compile.

It's basically the same as "why shouldn't I make all my parameters of type object"? Sure, you could do that. And if you do that, casting back wherever needed, your code would work. But I know I prefer

long Add(long x, long y) { return x + y; }

over

object Add(object x, object y) { return (long)x + (long)y; }

and I suspect that in this case, you do too. Yet this is exactly what you're doing when you make the parameter type EventArgs rather than Common.WinLose_ProgressStage.

  • my problem is that applying EventHandler ( as you saw in the previous post), an error would occur and i couldn't find solution to remove them, interestingly functionally the program is working, just that code is underlined in red. I'm agree that the function in the parent page is not guaranteed error-free, the parameter set of the function was public void Append_UC_Progress(object sender, Common.WinLose_ProgressStage e), just i have no choice to edit it for fixing that error, and eventually some other questions occurred. thanks – SKLTFZ Dec 20 '16 at 10:04
  • @SKLTFZ Yeah, I understand that, and if I had an answer for your other question, I'd be answering it too, but unfortunately I don't. –  Dec 20 '16 at 10:10