鸿门宴上项羽摔杯为号,埋伏两侧的刀斧手就会杀将而来,将刘邦一干人等就地伏法。这就是一个事件模型。
class Program { static void Main(string[] args) { XiangYu zhugong = new XiangYu(); ShaShou daofushou = new DaoFuShou(); ShaShou gongjianshou = new GongjianShou(); //6 杀手订阅主公的摔杯事件 zhugong.ShuaiBeiziEvent += new EventHandler<BeiziEventArgs>(daofushou.Action); zhugong.ShuaiBeiziEvent += gongjianshou.Action; //7 触发事件--- 谈判中(项羽可能随时会摔杯子) zhugong.Quanxiang(); Console.ReadKey(); } } //1 事件携带的附加信息 class BeiziEventArgs : EventArgs { //杯子材质 public string Metarials { get; set; } public BeiziEventArgs(string meterials) { this.Metarials = meterials; } } //2 定义事件拥有者 class XiangYu { private EventHandler<BeiziEventArgs> eventHandler; //3 定义摔杯事件 public event EventHandler<BeiziEventArgs> ShuaiBeiziEvent { add { eventHandler += value; } remove { eventHandler -= value; } } public void Quanxiang() { var ss = "你可以按下s来触发摔杯事件"; Console.WriteLine(ss); do { Console.WriteLine("宴会进行中..."); ss = Console.ReadLine(); } while ("s"!=ss); Console.WriteLine("项羽怒了 抄起酒杯摔了下去"); if (this.eventHandler!=null) { BeiziEventArgs attachinfo = new BeiziEventArgs("葡萄美酒夜光杯"); eventHandler.Invoke(this, attachinfo); } } } //4 定义事件响应者 abstract class ShaShou { //5 在响应者中 定义事件处理方法 public abstract void Action(object sender, BeiziEventArgs e); } class DaoFuShou : ShaShou { //刀斧手 public override void Action(object sender, BeiziEventArgs e) { Console.WriteLine($"{e.Metarials}被摔了,进去拿人"); } } class GongjianShou : ShaShou { //弓箭手 public override void Action(object sender, BeiziEventArgs e) { Console.WriteLine($"{e.Metarials}被摔了,准备放箭"); } }
运行结果:
代码分析:
class XiangYu { //3 定义摔杯事件 public event EventHandler<BeiziEventArgs> ShuaiBeiziEvent; public void Quanxiang() { var ss = "你可以按下s来触发摔杯事件"; Console.WriteLine(ss); do { Console.WriteLine("宴会进行中..."); ss = Console.ReadLine(); } while ("s"!=ss); Console.WriteLine("项羽怒了 抄起酒杯摔了下去"); if (this.ShuaiBeiziEvent!=null) { BeiziEventArgs attachinfo = new BeiziEventArgs("葡萄美酒夜光杯"); ShuaiBeiziEvent.Invoke(this, attachinfo); } } }
为什么说 public event EventHandler ShuaiBeiziEvent; 是一种语法糖,我们通过反编译工具可以看出:编译器看到这句代码时,为我们声明了一个私有的委托字段、一个add_xxx方法追加一个委托、一个remove_xxx方法移除一个委托
其实从反编译出来的代码可以看出,这两个方法的详细实现:
分析以上内容后我们发现,事件声明语法糖,是编译器以一种安全的方式为我们隐去了第一种方式的步骤,所以我们推荐第二种方式,但要知其然知其所以然;另外,事件是委托的包装器。他包装的这个委托内部维护了一个委托链。
本篇中并没有定义一种新的委托类型,而是使用了.NET为我们提供的EventHanler委托类型,为的是不做额外的工作(也不建议无脑定义委托类型,因为.NET为我们提供的委托类型大部分都够用了);若真的需要定义一种委托类型来约束事件处理方法的话,委托类型名要以EventHadnler结尾,如:ClickEventHandler;事件模式更多是用于客户端程序中的,因为他们是基于事件驱动的;事件用的多,而自己定义的情况很少,但是在我们使用事件前了解清楚事件的原理是十分重要的。
如本文的标题一样:事件是类的成员;类的三大成员:属性、方法、事件。以上便是对事件的总结,记录下来以便以后查阅。