繁体   English   中英

事件处理程序 <T> 和EventHandler

[英]EventHandler<T> and EventHandler

我想问一下EventHandlerEventHandler<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的通用变体。 通常,您将覆盖EventArgsEventHandler来提供自己的事件类型。 如果要将自定义属性传递给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.

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