我想问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));
答案 0 :(得分:6)
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或更高版本,则可以使用空条件运算符:
// If AppendProcess is null, the arguments won't even be evaluated
AppendProcess?.Invoke(this, new Common.WinLose_ProgressStage(...));
答案 1 :(得分:4)
EventHandler<T>
是EventHandler
的通用变体。通常,您会覆盖EventArgs
和EventHandler
来提出自己的事件类型。如果要将自定义属性传递给EventArgs
参数,则仍需要派生e
,但不需要再为EventHandler
创建自定义委托。你现在可以说:
public event EventHandler<SomeEventArgs> SomeEvent;
哪个更方便:
public delegate void SomeEventHandler(object sender, SomeEventArgs e);
public event SomeEventHandler SomeEvent;
当您的代理签名没有更改时,EventHandler<T>
使用起来会更加直接。
答案 2 :(得分:2)
来自您的其他问题:
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
时,这正是您正在做的事情。