[英]EventHandler<T> and EventHandler
我想问一下EventHandler
和EventHandler<T>
之间的区别。
以前,我实现了一个EventHandler
,它带有一个自定义EventArgs,可以将其从用户控件传递到父页面。
我以为我需要应用EventHandler< T >
,但是可以通过使用EventHandler
来实现。 (实际上,当我尝试应用EventHandler<T>
,出现了奇怪的错误,该程序可以运行,但是在IDE中显示了我无法解决的错误[ C#Custom EventHandler ])
因此,我想知道在什么情况下需要应用EventHandler < T >
?
public event EventHandler AppendProcess;
public event EventHandler<MyEventArg> AppendProcess;
---更新---这就是我在用户控件中调用事件的方式(正如我所说,我可以通过这样做将对象传递给父页面(尽管我不知道这样做是否正确)
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>
只是一个通用的EventHandler
类型,避免了您必须为每种要使用的EventArgs
声明新的委托类型。
以Control.KeyPress
为例。 声明为KeyPressEventHandler
类型的事件。 该委托仅声明为:
public delegate void KeyPressEventHandler(object sender, KeyPressEventArgs e)
如果EventHandler<T>
(和泛型)在创建时就已存在,则可以将事件声明为EventHandler<KeyPressEventArgs>
而保存委托声明。 就像EventHandler
一样,有很多代表,并且只有第二个参数的类型有所不同EventHandler<T>
避免了这种冗余。
不,如果你没有自己的自定义EventArgs
子类,没有理由使用EventHandler<T>
...但如果你这样做,这是更好的使用它,从而使处理事件的方法接收定制EventArgs
的子类一种强类型的方式。
顺便说一句,调用事件处理程序的方式不是线程安全的。 无效检查后,另一个线程可以取消订阅最终事件处理程序。 如果您使用的是C#5,则应将其编写为:
var handler = AppendProcess;
if (handler != null)
{
handler(this, new Common.WinLose_ProgressStage(...));
}
如果您使用的是C#6或更高版本,则可以使用null条件运算符:
// If AppendProcess is null, the arguments won't even be evaluated
AppendProcess?.Invoke(this, new Common.WinLose_ProgressStage(...));
EventHandler<T>
是EventHandler
的通用变体。 通常,您将覆盖EventArgs
和EventHandler
来提供自己的事件类型。 如果要将自定义属性传递给e
参数,则仍需要派生EventArgs
,但不再需要为EventHandler
创建自定义委托。 您现在可以说:
public event EventHandler<SomeEventArgs> SomeEvent;
哪个比:
public delegate void SomeEventHandler(object sender, SomeEventArgs e);
public event SomeEventHandler SomeEvent;
当您的委托人签名不变时, EventHandler<T>
更加易于使用。
从您的另一个问题:
Common.WinLose_ProgressStage wps = (Common.WinLose_ProgressStage)e;
根据方法的调用方式,转换可能会失败。 无法保证仅使用Common.WinLose_ProgressStage
调用事件处理程序,而无需检查完整程序即可对其进行检查。 也可以使用简单的EventArgs
来调用它:通过使参数类型EventArgs
成为可能。
EventHandler<T>
导致更多的编译时类型检查。 如果其他代码尝试传递EventArgs.Empty
,则该调用将仅无法编译。
它基本上与“为什么不让我的所有参数都成为object
类型”相同? 当然可以。 如果这样做,则可以在需要的地方回退,您的代码将起作用。 但我知道我更喜欢
long Add(long x, long y) { return x + y; }
过度
object Add(object x, object y) { return (long)x + (long)y; }
我怀疑在这种情况下,您也这样做。 但是,这正是在使参数类型为EventArgs
而不是Common.WinLose_ProgressStage
时正在执行的操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.