为什么在c#中强制事件订阅者具有特定的签名?

本文关键字:事件 为什么 | 更新日期: 2023-09-27 18:15:32

声明一个事件需要一个委托,订阅者将遵循这个委托(据我所知):

public delegate void SomeEventHandler(object source, EventArgs args);
public event SomeEventHandler EventHappend;

但是我们为什么需要这个委托呢?为什么不让任何带有任何签名的方法订阅事件呢?

为什么在c#中强制事件订阅者具有特定的签名?

以身作则…

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或字符串)?

为什么不让任何带有签名的方法订阅事件呢?

那么发送方如何知道要向订阅者传递哪些参数呢?

你可能知道,也可能不知道,这就是你如何引发你在问题中声明的事件:

EventHappened(this, new EventArgs());

当你引发一个事件时,你需要传递参数给它!假设您允许任何类型的方法订阅事件,那么我将使用此方法订阅EventHappened:

private void Foo(object sender, EventArgs e, int someNumber) {
    Console.WriteLine(someNumber);
}

当事件被触发时,将打印什么?没人知道!事件的发送方没有传递int参数!

你可以说

那么当我触发事件时,我将传递一个额外的int参数!

如果有另一个方法也订阅该事件,如:

private void Bar(object sender, EventArgs e, List<string> myList) {
    Console.WriteLine(myList);
}

这样,你的int参数与List<string>不兼容!

" c#不是Javascript。你不能只传递2个参数给一个需要3"的方法- sweep 2016

委托类型在这里是为了确保事件的发送方传递正确的参数,而订阅者是一个可以接受传递的参数作为参数的方法。

因为调用方希望能够将一组参数传递给被调用方。因此,调用方和被调用方都需要就某种契约达成一致,该契约定义了调用方期望和被调用方提供的参数集——而被调用方恰好是委托。

委托的"实例"无非是说:看这里,这里有一个"指针",指向一个符合我签名的方法,通过调用我,你可以执行这个方法。

示例:调用方想要传递自己的实例,一个string和一个int给被调用方。如果被调用方只接受bool,那该如何工作呢?

可以引入约定,每个事件处理程序都需要遵守签名:

public void Method(object sender, EventArgs e);

使以下事件声明语法始终有效:

public event EventHandler<EventArgs> MyEvent;

但是在很多情况下,如果你想传递任何有效负载给被调用者,你需要创建一个来自EventArgs的类。