本章主要记录如何使用事件。
【参考文章】《c# 图解教程》(第五版)
事件
事件是类或结构的成员。事件成员被隐式自动初始化为null。
当一个特定的程序事件发生时,程序的其他部分可以得到该事件已经发生的通知。
事件和委托类似。实际上,事件就像是专门用于某种特殊用途的简单委托。
事件包含了一个私有的委托,关于事件的私有委托需要了解:
- 事件提供了对它的私有控制委托的结构化访问,也就是说,无法直接访问该委托。
- 事件中可用的操作比委托要少,只能添加,删除或调用事件处理程序。
- 事件被触发时,它调用委托来依次调用调用列表中的方法。
事件必要5元素
- 声明委托(类型):事件和事件处理程序必须有共同的参数和返回类型,它们通过委托类型进行描述。
delegate void Handler();
- 声明事件处理程序(订阅者):订阅者类中会在事件触发时执行的方法声明。
void IncrementDozensCount()
{
DozensCount++;
}
- 声明事件(发布者):发布者必须声明一个订阅者可以注册的事件成员。当类事件为public时,称为发布了事件。
class Incrementer
{
//关键字:event+委托类型:EventHandler+事件名:CountedADozen1
public event EventHandler CountedADozen1;
//多个事件用逗号隔开
public event EventHandler MyEvent1, MyEvent2,MyEvent3;
//static 让事件变成静态的
public static event EventHandler CountedADozen2;
}
- 订阅事件/注册事件(一般是订阅者):订阅者必须注册事件,才能在事件被触发时得到通知。
//方法引用形式
//incrementer: 类; IncrementDozensCount: 实例方法
incrementer.CounterADozen += IncrementDozensCount;
//方法引用形式
//CounterADozen: 事件成员; ClassB.CounterHandlerB: 静态方法
incrementer.CounterADozen += ClassB.CounterHandlerB;
//委托形式
mc.CounterADozen += new EventHandler(cc.CounterHandlerC);
//Lambda形式
mc.CounterADozen += () => DozensCount++; //隐式+无参
//匿名方法
mc.CounterADozen += delegate { DozensCount++ };
- 触发事件(发布者):发布者类中触发事件,并导致调用注册的所有事件处理程序的代码。
if(CounterADozen != null) //确认有方法可以执行
{
//CounterADozen: 事件名称; (source, args): 参数列表
CounterADozen(source, args); //触发事件
}
无参事件demo
delegate void Handler(); //声明委托
// 发布者:声明事件+触发事件
class Incrementer
{
public event Handler CountedADozen; //声明事件
public void DoCount()
{
for (int i = 1; i<100; i++)
{
if (i%12 ==0)
{
if (null != CountedADozen)
{
CountedADozen(); //触发事件
}
}
}
}
}
// 订阅者:订阅事件+声明事件处理程序
class Dozens
{
public int DozensCount { get; private set; }
public Dozens(Incrementer incrementer)
{
DozensCount = 0;
incrementer.CountedADozen += IncrementDozensCount; //订阅事件(注册事件)
}
void IncrementDozensCount()
{
DozensCount++; //声明事件处理程序
}
}
class Program
{
static void Main()
{
Incrementer incrementer = new Incrementer();
Dozens dozensCounter = new Dozens(incrementer);
incrementer.DoCount();
Console.WriteLine("Number of dozens = {0}", dozensCounter.DozensCount);
//执行顺序
//1. 创建 Incrementer 实例
//2.创建 Dozens 实例,在构造函数中为 Incrementer 实例订阅事件
//3.Incrementer 实例执行 DoCount 方法,在满足条件时 触发事件,执行事件处理程序
}
}
输出结果:
Number of dozens = 8
有参事件demo
public class IncrementerEventArgs : EventArgs //自定义类派生自 EventArgs
{
public int IterationCount { get; set; } //存储一个整数
}
// 发布者:声明事件+触发事件
class Incrementer
{
public event EventHandler<IncrementerEventArgs> CountedADozen; //声明事件
public void DoCount()
{
IncrementerEventArgs args = new IncrementerEventArgs();
for (int i = 1; i < 100; i++)
{
if (i % 12 == 0 && null != CountedADozen)
{
args.IterationCount = i;
CountedADozen(this, args); //触发事件,并传递参数
}
}
}
}
// 订阅者:订阅事件+声明事件处理程序
class Dozens
{
public int DozensCount { get; private set; }
public Dozens(Incrementer incrementer)
{
DozensCount = 0;
incrementer.CountedADozen += IncrementDozensCount; //订阅事件(注册事件)
}
void IncrementDozensCount(object source, IncrementerEventArgs e)
{
Console.WriteLine($"Incremented at iteration: {e.IterationCount} in {source.ToString()}");
DozensCount++; //声明事件处理程序
}
}
class Program
{
static void Main()
{
Incrementer incrementer = new Incrementer();
Dozens dozensCounter = new Dozens(incrementer);
incrementer.DoCount();
Console.WriteLine("Number of dozens = {0}", dozensCounter.DozensCount);
}
}
输出结果:
Incremented at iteration: 12 in DelegateEventDemo.EventDemo.Incrementer
Incremented at iteration: 24 in DelegateEventDemo.EventDemo.Incrementer
Incremented at iteration: 36 in DelegateEventDemo.EventDemo.Incrementer
Incremented at iteration: 48 in DelegateEventDemo.EventDemo.Incrementer
Incremented at iteration: 60 in DelegateEventDemo.EventDemo.Incrementer
Incremented at iteration: 72 in DelegateEventDemo.EventDemo.Incrementer
Incremented at iteration: 84 in DelegateEventDemo.EventDemo.Incrementer
Incremented at iteration: 96 in DelegateEventDemo.EventDemo.Incrementer
Number of dozens = 8