事件
事件(event)基于委托,为委托提供一个发布/订阅机制,我们可以说事件是一种具有特殊签名的委托。
什么是事件?
事件(event)是类或对象向其他类或对象通知发生的事情的一种特殊签名的委托。
事件的声明
首先必须声明该事件的委托类型。例如
public delegate void BoilerLogHandler(string status);
然后,声明事件本身,使用 event 关键字:
public event BoilerLogHandler BoilerEventLog;
事件使用event关键字来声明,他的返回值是一个委托类型。
通常事件的命名,以名字+Event作为他的名字。
事件与委托的联系与区别
事件是一种特殊的委托,或者说是受限制的委托,在定义事件类的外部,只能施加+=、-=操作符。二者本质上是一个东西。
委托可以在外部被直接调用,但事件不可以在定义类的外部被触发。
class Program
{
static void Main(string[] args)
{
ToolMan toolMan = new ToolMan("小明");
LazyMan lazyMan1 = new LazyMan("张三");
LazyMan lazyMan2 = new LazyMan("李四");
LazyMan lazyMan3 = new LazyMan("王五");
toolMan.DownStairdelegate += lazyMan1.TakeFood;
toolMan.DownStairdelegate += lazyMan2.TakePackage;
toolMan.DownStairdelegate += lazyMan3.TakeFood;
toolMan.DownStair();
Console.WriteLine("。。。。。。。。。。。。。。。。。。。。");
toolMan.DownStairdelegate -= lazyMan3.TakeFood;
toolMan.DownStair();
Console.Read();
}
}
delegate void DownStairdelegate();
internal class ToolMan
{
public string Name { get; private set; }
public DownStairdelegate DownStairdelegate = null;
public ToolMan(string name)
{
this.Name = name;
}
public void DownStair()
{
Console.WriteLine("工具人"+Name + "下楼了");
if(DownStairdelegate != null)
{
DownStairdelegate();
}
}
}
internal class LazyMan
{
public string Name { get; private set; }
public LazyMan(string name)
{
this.Name = name;
}
public void TakeFood()
{
Console.WriteLine("给" + Name + "拿外卖");
}
public void TakePackage()
{
Console.WriteLine("给" + Name + "拿快递");
}
}
运行结果:
工具人小明下楼了
给张三拿外卖
给李四拿快递
给王五拿外卖
。。。。。。。。。。。。。。。。。。。。
工具人小明下楼了
给张三拿外卖
给李四拿快递
是用委托来进行函数绑定,这样执行貌似没什么问题,但是…
class Program
{
static void Main(string[] args)
{
ToolMan toolMan = new ToolMan("小明");
LazyMan lazyMan1 = new LazyMan("张三");
LazyMan lazyMan2 = new LazyMan("李四");
LazyMan lazyMan3 = new LazyMan("王五");
toolMan.DownStairdelegate += lazyMan1.TakeFood;
toolMan.DownStairdelegate += lazyMan2.TakePackage;
toolMan.DownStairdelegate = lazyMan3.TakeFood;//有可能一不小心覆盖掉了
toolMan.DownStair();
Console.Read();
}
}
运行结果:
工具人小明下楼了
给王五拿外卖
有可能会被一不小心覆盖掉原有的需执行内容
static void Main(string[] args)
{
ToolMan toolMan = new ToolMan("小明");
LazyMan lazyMan1 = new LazyMan("张三");
LazyMan lazyMan2 = new LazyMan("李四");
LazyMan lazyMan3 = new LazyMan("王五");
toolMan.DownStairdelegate += lazyMan1.TakeFood;
toolMan.DownStairdelegate += lazyMan2.TakePackage;
toolMan.DownStairdelegate += lazyMan3.TakeFood;
toolMan.DownStairdelegate();//外部进行了触发
Console.Read();
}
}
运行结果:
给张三拿外卖
给李四拿快递
给王五拿外卖
有可能未达到函数运行条件,直接调用委托而执行了函数。
所以引入事件来规避一些异常情况,代码修改方法如下:
//将ToolMan类中的
public DownStairdelegate DownStairdelegate = null;
//改为
public event DownStairdelegate DownStairdelegate = null;
将委托改为事件之后,直接赋值与直接调用都将不被允许,这样的话就规避掉了委托在此应用下的弊端。