C# 事件

278 阅读3分钟

「这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战」。

事件和委托

事件有很多方面和委托相似。其实,事件就好像是被简化的针对特殊用途的委托。 下面是一些关于事件的重要事项:

  1. 触发事件(raise) 调用(invoke) 或 触发(fire)等术语。当事件被触发时,所有注册到它的方法都会被依次调用。
  2. 发布者(publisher) 让事件被其他类或结构可见并使用的类或结构
  3. 订阅者(subscriber) 把事件和发布者关联注册的类或结构
  4. 事件处理程序(event handler) 注册到事件的方法

事件有私有委托

事件之所以和委托类似是有充分理由的。事件包含了一个私有委托。有关事件的私有委托需要了解的重要事项如下:

  • 事件提供了对它的私有委托的结构化访问
  • 与委托中的很多其他 操作不一样,对于事件我们只能添加、删除或者调用事件处理程序
  • 事件被触发时,它调用委托来依次调用列表中的方法

声明事件

public event EventHandler Elaspsed;
//event 为事件的关键字
//EventHandler为委托类型,用来规定事件接受的事件处理程序

事件是成员

  • 由于事件不是类型,我们不能使用new表达式来创建它的对象
  • 由于事件是成员,我们必须在类或结构中声明,而不能在一段可执行代码中声明它
  • 事件成员被隐式自动初始化为null

触发事件

if (Elapsed != null){
  Elapsed(source, args);
}

订阅事件

要为事件添加事件处理程序,处理程序必须有和事件委托一致的返回类型和签名。

  • 使用+=为事件添加事件处理程序
  • 方法可以是下面的任意一个:
    • 实例方法
    • 静态方法
    • 匿名方法
    • lambda表达式

移除事件处理程序

myEvent -= EventHandle;

标准事件的用法

从事件的定义来看可以知道:委托决定了事件。所以说标准事件其实说的就是标准委托。 标准委托长得这个样子:

public delegate void EventHandle(object sender, EventArgs e);
//sender:保存触发事件的对象的引用
//e     :保存有关状态对于应用程序来说是否合适的状态信息

EventHandler第二个参数是EventArgs类的对象,它声明在System命名空间中。有以下几点需要注意:

  1. EventArgs被设计为不能传递任何数据。它用于不需要传递数据的事件处理程序
  2. 如果你希望传递数据,必须声明一个从EventArgs继承的类,使用合适的字段来保存需要传递的数据
public class MyTCEventArgs:EventArgs
{
public string message;
public MyTCEventArgs(string s)
  {
    message = s;
  }
}

使用自定义的委托:

//使用非凡性委托,即一个全新的委托
public delege void MyTCEventHandler(object sender, MyTCEventArgs e);
//使用EventHandler泛型委托的方式
public event EventHandler<MyTCEventArgs> Elapsed;