EventHandler <t>和EventHandler

时间:2016-12-20 09:44:38

标签: c# asp.net 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));

3 个答案:

答案 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的通用变体。通常,您会覆盖EventArgsEventHandler来提出自己的事件类型。如果要将自定义属性传递给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时,这正是您正在做的事情。