卧谈会:委托与事件
为什么要出现委托,为什么又要出现事件,事件和委托又是什么关系,既然有网友问到了,我也回顾一下。 1.委托的出现是基于多态,增加相同类型函数操作代码的复用性以减少冗余代码。 2.委托和事件没有可比性,因为委托是类型,事件是对象。 对于第一点大家都应该特别熟悉,这个帖子主要就看第二个问题。 首先我用委托方式实现的一个事件(之后会用标准的event方式实现),但是应该有个观念事件的内部是用委托实 现的.
1.我首先使用委托方式实现的一个事件.
我首先定义了一个旅行社TravelagencyDelegate用来代理购票业务。 之后定义了一个售票点里面包含了:买票行为,以及权限证明。
好了上代码:
1 using System; 2 3 namespace 委托与事件回顾 4 { 5 //首先我们定义一个委托(美女售票代理人她可以替你指向各种类型的票) 6 public delegate void TravelagencyDelegate();//她是一个类型不是对象 7 class 售票处 8 { 9 //定义一个买票事件用来指向各种类型的票 10 public TravelagencyDelegate Ontickets;//她是一个对象 11 12 //好了既然可以买票当然要让外部知道你有乘某种交通工具的权利否则就是黑箱操作,外面不买账 13 public void RightofYou() 14 { 15 if (Ontickets != null) 16 { 17 Ontickets(); 18 } 19 else 20 { 21 Console.WriteLine("本公司没有该游客的购票记录!"); 22 } 23 } 24 } 25 class 安检口 26 { 27 public static void Main() 28 { 29 售票处 seller = new 售票处(); 30 seller.Ontickets += byBus; 31 seller.RightofYou(); 32 Console.ReadKey(); 33 } 34 public static void byBus() 35 { 36 Console.WriteLine("可以乘大巴!"); 37 } 38 public static void byTrain() 39 { 40 Console.WriteLine("可以乘火车!"); 41 } 42 public static void byPlane() 43 { 44 Console.WriteLine("可以乘飞机!"); 45 } 46 } 47 }
上面的代码貌似完成了事件的功能,但是我们如果在进站口遇到了黄牛买了张套牌票呢,依然得到了额外的一次权限证明,如下:
1 class 安检口 2 { 3 public static void Main() 4 { 5 售票处 seller = new 售票处(); 6 seller.Ontickets += byBus; 7 //此时遇到了黄牛买了张套牌票 8 seller.Ontickets();//因此可以获得额外的一票 9 seller.RightofYou(); 10 Console.ReadKey(); 11 } 12 public static void byBus() 13 { 14 Console.WriteLine("可以乘大巴!"); 15 } 16 public static void byTrain() 17 { 18 Console.WriteLine("可以乘火车!"); 19 } 20 public static void byPlane() 21 { 22 Console.WriteLine("可以乘飞机!"); 23 } 24 }
甚至售票员正好和你有夺妻之恨,偷偷跑到安检处把你的权限指向了null,你妹没权限了。如下:
1 class 安检口 2 { 3 public static void Main() 4 { 5 售票处 seller = new 售票处(); 6 //此时遇到了情敌售票员 7 seller.Ontickets =null; 8 seller.RightofYou(); 9 Console.ReadKey(); 10 }
这个世界太疯狂了,售票点啥人都有啊,但是还是政府有办法(于是出现了标准的事件event)打击着一切,黄牛,人情票都不起作用了,我们先这样解决。
从上面的代码可以看到原因是我们直接操作了Ontickets,我们只要做个小动作就可以防范这种漏洞。
private TravelagencyDelegate Ontickets;//我们将它封装起来 public void BuyTickets(TravelagencyDelegate d) { Ontickets += d; }
public void refundTickets(TravelagencyDelegate d)
{
Ontickets -= d;
}
这样我们在售票处把事都给办完了,别的地方也没权限干涉了。
你妹:要你再seller.Ontickets =null;或者seller.Ontickets+=byBus;seller.Ontickets();
你只能乖乖这样:
1 class 安检口 2 { 3 public static void Main() 4 { 5 售票处 seller = new 售票处(); 6 seller.BuyTickets(byBus); 7 Console.ReadKey(); 8 } 9 public static void byBus() 10 { 11 Console.WriteLine("可以乘大巴!"); 12 } 13 public static void byTrain() 14 { 15 Console.WriteLine("可以乘火车!"); 16 } 17 public static void byPlane() 18 { 19 Console.WriteLine("可以乘飞机!"); 20 } 21 }
2.下面我用用标准的event方式实现上面的方法 完成订票和退票。
1 using System; 2 3 namespace 委托与事件回顾 4 { 5 //首先我们定义一个委托(美女售票代理人她可以替你指向各种类型的票) 6 public delegate void TravelagencyDelegate();//她是一个类型不是对象 7 class 售票处 8 { 9 //定义一个买票事件用来指向各种类型的票 10 private TravelagencyDelegate Ontickets;//她是一个对象 11 public event TravelagencyDelegate Onbuy 12 { 13 add 14 { 15 Ontickets += value; 16 } 17 remove 18 { 19 Ontickets -= value; 20 } 21 } 22 23 //好了既然可以买票当然要让外部知道你有乘某种交通工具的权利否则就是黑箱操作,外面不买账 24 public void RightofYou() 25 { 26 if (Ontickets != null) 27 { 28 Ontickets(); 29 } 30 else 31 { 32 Console.WriteLine("本公司没有该游客的购票记录!"); 33 } 34 } 35 } 36 class 安检口 37 { 38 public static void Main() 39 { 40 售票处 seller = new 售票处(); 41 seller.Onbuy+=new TravelagencyDelegate(byBus); 42 seller.Onbuy+=new TravelagencyDelegate(byPlane); 43 seller.Onbuy-= new TravelagencyDelegate(byBus); 44 seller.RightofYou(); 45 Console.ReadKey(); 46 } 47 public static void byBus() 48 { 49 Console.WriteLine("可以乘大巴!"); 50 } 51 public static void byTrain() 52 { 53 Console.WriteLine("可以乘火车!"); 54 } 55 public static void byPlane() 56 { 57 Console.WriteLine("可以乘飞机!"); 58 } 59 } 60 }
这样外部只可以添加和移除监听不能直接等于或者指向方法。private TravelagencyDelegate Ontickets;//用来保存监听。
事件可以看做是对委托的封装。
当然我们可以简化成一下方式。
1 public event TravelagencyDelegate Onbuy; 2 public void RightofYou() 3 { 4 if (Onbuy != null) 5 { 6 Onbuy(); 7 } 8 else 9 { 10 Console.WriteLine("本公司没有该游客的购票记录!"); 11 } 12 }
它其实由编译器自动生成了一个中间的私有变量,原理是一样的。