事件
事件(event)基于委托,为委托提供了一个发布/订阅机制,我们可以说事件是一种具有特殊签名的委托。
什么是事件?
事件(Event)是类或对象向其他类或对象通知发生的事情的一种特殊签名的委托.
事件的声明
public event 委托类型 事件名;
事件使用event关键词来声明,他的返回类值是一个委托类型。
通常事件的命名,以名字+Event 作为他的名称,在编码中尽量使用规范命名,增加代码可读性。
为了更加容易理解事件,我们还是以前面的动物的示例来说明,有三只动物,猫(名叫Tom),还有两只老鼠(Jerry和Jack),当猫叫的时候,触发事件(CatShout),然后两只老鼠开始逃跑(MouseRun)。接下来用代码来实现。(设计模式-观察者模式)
Cat类和Mouse类:
class Cat
{
string catName;
string catColor { get; set; }
public Cat(string name, string color)
{
this.catName = name;
catColor = color;
}
public void CatShout()
{
Console.WriteLine(catColor+" 的猫 "+catName+" 过来了,喵!喵!喵!\n");
//猫叫时触发事件
//猫叫时,如果CatShoutEvent中有登记事件,则执行该事件
if (CatShoutEvent != null)
CatShoutEvent();
}
public delegate void CatShoutEventHandler();
public event CatShoutEventHandler CatShoutEvent;
}
class Mouse
{
string mouseName;
string mouseColor { get; set; }
public Mouse(string name, string color)
{
this.mouseName = name;
this.mouseColor = color;
}
public void MouseRun()
{
Console.WriteLine(mouseColor + " 的老鼠 " + mouseName + " 说:\"老猫来了,快跑!\" \n我跑!!\n我使劲跑!!\n我加速使劲跑!!!\n");
}
}
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine("场景说明: 一个月明星稀的午夜,有两只老鼠在偷油吃\n");
Mouse Jerry = new Mouse("Jerry", "白色");
Mouse Jack = new Mouse("Jack", "黄色");
Console.WriteLine("场景说明: 一只黑猫蹑手蹑脚的走了过来\n");
Cat Tom = new Cat("Tom", "黑色");
Console.WriteLine("场景说明: 为了安全的偷油,登记了一个猫叫的事件\n");
Tom.CatShoutEvent += new Cat.CatShoutEventHandler(Jerry.MouseRun);
Tom.CatShoutEvent += new Cat.CatShoutEventHandler(Jack.MouseRun);
Console.WriteLine("场景说明: 猫叫了三声\n");
Tom.CatShout();
}
}
运行:
场景说明: 一个月明星稀的午夜,有两只老鼠在偷油吃
场景说明: 一只黑猫蹑手蹑脚的走了过来
场景说明: 为了安全的偷油,登记了一个猫叫的事件
场景说明: 猫叫了三声
黑色 的猫 Tom 过来了,喵!喵!喵!
白色 的老鼠 Jerry 说:"老猫来了,快跑!"
我跑!!
我使劲跑!!
我加速使劲跑!!!
黄色 的老鼠 Jack 说:"老猫来了,快跑!"
我跑!!
我使劲跑!!
我加速使劲跑!!!
事件与委托的联系和区别
事件是一种特殊的委托,或者说是受限制的委托,是委托一种特殊应用,只能施加+=,-=操作符。二者本质上是一个东西。
event ActionHandler Tick; // 编译成创建一个私有的委托示例, 和施加在其上的add, remove方法.
event只允许用add, remove方法来操作,这导致了它不允许在类的外部被直接触发,只能在类的内部适合的时机触发。委托可以在外部被触发,但是别这么用。
使用中,委托常用来表达回调,事件表达外发的接口。
委托和事件支持静态方法和成员方法, delegate(void * pthis, f_ptr), 支持静态返方法时, pthis传null.支持成员方法时, pthis传被通知的对象.
委托对象里的三个重要字段是, pthis, f_ptr, pnext, 也就是被通知对象引用, 函数指针/地址, 委托链表的下一个委托节点.