简体   繁体   English

事件处理程序 <T> 和EventHandler

[英]EventHandler<T> and EventHandler

I want to ask the different between EventHandler and EventHandler<T> . 我想问一下EventHandlerEventHandler<T>之间的区别。

Previously I have implemented a EventHandler , with a custom EventArgs which can be passed to the parent page from the user control. 以前,我实现了一个EventHandler ,它带有一个自定义EventArgs,可以将其从用户控件传递到父页面。

I thought I need to apply EventHandler< T > , however it can be implemented by using EventHandler . 我以为我需要应用EventHandler< T > ,但是可以通过使用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 ]) (实际上,当我尝试应用EventHandler<T> ,出现了奇怪的错误,该程序可以运行,但是在IDE中显示了我无法解决的错误[ C#Custom EventHandler ])

Thus, I want to know in what situation I need to apply EventHandler < T > ? 因此,我想知道在什么情况下需要应用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));

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. EventHandler<T>只是一个通用的EventHandler类型,避免了您必须为每种要使用的EventArgs声明新的委托类型。

Consider Control.KeyPress for example. Control.KeyPress为例。 It's declared as an event of type KeyPressEventHandler . 声明为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. 如果EventHandler<T> (和泛型)在创建时就已存在,则可以将事件声明为EventHandler<KeyPressEventArgs>而保存委托声明。 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. 就像EventHandler一样,有很多代表,并且只有第二个参数的类型有所不同EventHandler<T>避免了这种冗余。

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. 不,如果你没有自己的自定义EventArgs子类,没有理由使用EventHandler<T> ...但如果你这样做,这是更好的使用它,从而使处理事件的方法接收定制EventArgs的子类一种强类型的方式。

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: 如果您使用的是C#5,则应将其编写为:

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: 如果您使用的是C#6或更高版本,则可以使用null条件运算符:

// If AppendProcess is null, the arguments won't even be evaluated
AppendProcess?.Invoke(this, new Common.WinLose_ProgressStage(...));

EventHandler<T> is the generic variant of EventHandler . EventHandler<T>EventHandler的通用变体。 Usually, you would override EventArgs and EventHandler to come up with an own event type. 通常,您将覆盖EventArgsEventHandler来提供自己的事件类型。 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. 如果要将自定义属性传递给e参数,则仍需要派生EventArgs ,但不再需要为EventHandler创建自定义委托。 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. 当您的委托人签名不变时, EventHandler<T>更加易于使用。

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. 无法保证仅使用Common.WinLose_ProgressStage调用事件处理程序,而无需检查完整程序即可对其进行检查。 It could be called with a plain EventArgs too: you made that possible by making the parameter type EventArgs . 也可以使用简单的EventArgs来调用它:通过使参数类型EventArgs成为可能。

EventHandler<T> causes more compile-time type checking. EventHandler<T>导致更多的编译时类型检查。 If other code attempts to pass in EventArgs.Empty , the call would simply fail to compile. 如果其他代码尝试传递EventArgs.Empty ,则该调用将仅无法编译。

It's basically the same as "why shouldn't I make all my parameters of type object "? 它基本上与“为什么不让我的所有参数都成为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 . 但是,这正是在使参数类型为EventArgs而不是Common.WinLose_ProgressStage时正在执行的操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM