声明一个事件需要订阅者将遵循的代表(据我所知):
public delegate void SomeEventHandler(object source, EventArgs args);
public event SomeEventHandler EventHappend;
但为什么我们需要这个代表呢?为什么不允许任何签名方法订阅该活动?
答案 0 :(得分:2)
保持你的榜样......
class A
{
public event EventHappend; // Invalid C# but let's pretend it could work
public void DoSomething()
{
...
if (EventHappend != null)
{
// What should ??? be replaced with?
EventHappend(???);
}
}
}
class B
{
public B()
{
new A().EventHappend += EventHandler;
}
public void EventHandler(int anInt)
...
}
class C
{
public C()
{
new A().EventHappend += EventHandler;
}
public void EventHandler(string aString)
...
}
应该怎么做?被替换为处理B和C的情况(参数中的int或字符串)?
答案 1 :(得分:1)
因为调用者希望能够将一组参数传递给被调用者。因此,调用者和被调用者都需要就某种合同达成一致,该合同定义了调用者期望的参数集以及被调用者提供的参数集 - 恰好是委托者。
"实例"代表说的只不过:看这里,这里是一个"指针"一个符合我签名的方法,并通过调用我可以执行该方法。
示例:调用者想要将自己的实例string
和int
传递给被调用者。如果被叫方只接受bool
?
有人可能已经引入了每个事件处理程序需要坚持签名的约定:
public void Method(object sender, EventArgs e);
以便以下事件声明语法始终有效:
public event EventHandler<EventArgs> MyEvent;
但是,如果您想将任何有效负载传递给被调用者,那么在许多情况下这将要求您创建一个派生自EventArgs
的类。
答案 2 :(得分:1)
为什么不让任何带有任何签名的方法订阅该事件?
那么发件人将如何知道要传递给订阅者的参数?
您可能知道也可能不知道,这就是您提出您在问题中声明的事件的方式:
EventHappened(this, new EventArgs());
每当你举起一个事件时,你需要将参数传递给它!我们假设您允许任何类型的方法订阅该事件,然后我将使用此方法订阅{{ 1}}:
EventHappened
当事件被提出时,会打印什么?没人知道!事件的发送者没有传递一个int参数!
你可能会说
然后,当我举起事件时,我只会传递一个额外的int参数!
如果还有其他方法也订阅了该事件,如下所示:
private void Foo(object sender, EventArgs e, int someNumber) {
Console.WriteLine(someNumber);
}
这样,你的int参数与private void Bar(object sender, EventArgs e, List<string> myList) {
Console.WriteLine(myList);
}
不兼容!
“C#不是Javascript。您不能只将2个参数传递给需要3的方法” - Sweeper 2016
委托类型用于确保事件的发送者传递正确的参数,订阅者是一个可以接受传递的参数作为参数的方法。