一、引言
前几天正在找工作的师兄考我:“你刚刚学了 C# ,什么是委托?什么是事件?有什么区别?分得清吗?”
我其实没搞懂,只能回答:“好像事件是委托的一种。”
师兄却告诉我:委托是包含在事件内的一部分。
本来我就是照着书背了一句,但根据我写 WinForm 的经验,师兄说的又没错,故而开始面向百度学习,有了这篇小文。
在开始阅读本文之前,你需要对委托有一个初步的认识,需要的朋友可以看我的上一篇小文 C#(二)——委托 。
二、什么是事件
事件(Event) 基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些提示信息,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断等。
C# 中使用事件机制实现 线程间的通信。
例如在登录 QQ 软件时需要输入用户名和密码,然后单击“登录”按钮来登录 QQ,此时单击按钮的动作会触发一个按钮的单击事件来完成执行相应的代码实现登录的功能。
graph LR
动作--触发--> 事件 --执行--> 事件处理程序
在 C# 语言中,Windows 应用程序、 ASP.NET 网站程序等类型的程序都离不开事件的应用。
事件其实是一种特殊的委托,事件要与委托一起使用。事件定义的语法形式如下:
访问修饰符 event 委托名 事件名 ;
在这里,由于在事件中使用了委托,因此需要定义委托、定义事件、定义事件所调用的处理方法,并通过事件来调用委托。
graph LR
触发事件的方法--触发--> 事件 --通过委托指向--> 调用的处理方法 --执行--> 事件处理程序
三、事件怎么使用
借用一下 C语言中文网 中两个很好的例程,进行分析。
1、控制台输岀“Hello Event!”
class Program
{
//定义委托
public delegate void SayDelegate();
//定义事件
public event SayDelegate SayEvent;
//定义委托中调用的方法
public void SayHello()
{
Console.WriteLine("Hello Event!");
}
//创建触发事件的方法
public void SayEventTrigger()
{
//触发事件,必须与事件是同名方法
SayEvent();
}
static void Main(string[] args)
{
//创建Program类的实例
Program program = new Program();
//实例化事件,并使用委托指向调用的处理方法
program.SayEvent = new SayDelegate(program.SayHello);
//调用触发事件的方法
program.SayEventTrigger();
}
}
把它套入上一章末尾的框图就是
graph LR
SayEventTrigger--触发--> SayEvent --通过委托指向--> SayHello --执行--> WriteLine
2、多播委托-购买不同商品
class Program
{
static void Main(string[] args)
{
//创建MyEvent类的实例
MyEvent myEvent = new MyEvent();
//实例化事件,并使用委托指向调用的处理方法
myEvent.BuyEvent += new MyEvent.BuyDelegate(MyEvent.BuyFood);
myEvent.BuyEvent += new MyEvent.BuyDelegate(MyEvent.BuyCake);
myEvent.BuyEvent += new MyEvent.BuyDelegate(MyEvent.BuyFlower);
//调用触发事件的方法
myEvent.InvokeEvent();
}
}
class MyEvent
{
//定义委托
public delegate void BuyDelegate();
//定义事件
public event BuyDelegate BuyEvent;
//定义委托中使用的方法
public static void BuyFood()
{
Console.WriteLine("购买快餐!");
}
public static void BuyCake()
{
Console.WriteLine("购买蛋糕!");
}
public static void BuyFlower()
{
Console.WriteLine("购买鲜花!");
}
//创建触发事件的方法
public void InvokeEvent()
{
//触发事件,必须和事件是同名方法
BuyEvent();
}
}
把它套入上一章末尾的框图就是
graph LR
InvokeEvent--触发--> BuyEvent
BuyEvent --通过委托指向--> BuyFood --执行--> 购买快餐
BuyEvent --通过委托指向--> BuyCake --执行--> 购买蛋糕
BuyEvent --通过委托指向--> BuyFlower --执行--> 购买鲜花
事件使用 发布-订阅(publisher-subscriber) 模型。
包含事件的类用于发布事件,这被称为 发布器(publisher) 类,如上面的 Program 类;其他接受该事件的类被称为 订阅器(subscriber) 类,如上面的 MyEvent 类。
发布器(publisher) 是一个包含事件和委托定义的对象,如上面的 Program 类的静态对象 Main 。事件和委托之间的联系也定义在这个对象中。发布器(publisher)类的对象调用这个事件,并通知其他的对象。
订阅器(subscriber) 是一个接受事件并提供事件处理程序的对象,如上面的 MyEvent 类的实例 myEvent 。发布器(publisher)类中的委托调用订阅器(subscriber)类中的方法(事件处理程序)。
需要注意的是,如果事件的定义和调用不在同一个类中,实例化事件只能用+=或者-=。即,在上面的代码中,实例化事件的代码只能写成
myEvent.BuyEvent += new MyEvent.BuyDelegate(MyEvent.BuyFood);的形式,而不能使用
myEvent.BuyEvent = new MyEvent.BuyDelegate(MyEvent.BuyFood);。