委托的应用之事件
前言
上一个章节介绍了委托,这里我们再通过一个例子继续巩固一下委托并引入事件 。
为了便于理解,这里还是引入一个很老的例子:
因为一只猫叫了一声 接着老鼠被吓跑 小孩哭也了起来 最后妈妈也被吵醒。
下面用代码来实现这些功能
1 ///2 /// 猫类 3 /// 4 public class Cat 5 { 6 /// 7 /// 猫叫的方法 8 /// 9 public void Miao() 10 { 11 Console.WriteLine("猫喵了一声"); 12 13 new Mouse().Run(); 14 new Baby().Cry(); 15 new Mother().Awake(); 16 } 17 } 18 19 20 /// 21 /// 老鼠类 22 /// 23 public class Mouse 24 { 25 /// 26 /// 老鼠跑的方法 27 /// 28 public void Run() 29 { 30 Console.WriteLine("老鼠开始跑"); 31 } 32 } 33 34 /// 35 /// 小孩类 36 /// 37 public class Baby 38 { 39 /// 40 /// 小孩哭的方法 41 /// 42 public void Cry() 43 { 44 Console.WriteLine("婴儿哭了起来"); 45 } 46 } 47 48 /// 49 /// 妈妈类 50 /// 51 public class Mother 52 { 53 /// 54 /// 妈妈醒的方法 55 /// 56 public void Awake() 57 { 58 Console.WriteLine("妈妈被吵醒了"); 59 } 60 } 61 62 class Program 63 { 64 static void Main(string[] args) 65 { 66 { 67 //直接调用 68 new Cat().Miao(); 69 } 70 Console.ReadLine(); 71 } 72 }
代码写完了,功能完成了 。
那么问题还是那个问题:耦合,依赖,不扩展,增加类的动作或者调整顺序都会导致Cat类被修改。
为解决这一问题 还是用前面用的委托(上一章就是学习的委托的接解藕功能),
代码如下:
在Cat类声明一个委托
1 //这里定义一个委托 2 public delegate void MiaoHandel(); 3 4 ///5 /// 猫类 6 /// 7 public class Cat 8 { 9 /// 10 /// 猫叫的方法 11 /// 12 public void Miao() 13 { 14 Console.WriteLine("猫喵了一声"); 15 } 16 }
外面再给委托添加后和删除方法,还可以任意调整顺序且不用修改Cat类。
class Program { static void Main(string[] args) { { //直接调用 new Cat().Miao(); } Console.WriteLine("--------------------------------"); { //用委托来调用 MiaoHandel miaoHandel=new MiaoHandel(new Cat().Miao); miaoHandel += new Mouse().Run; miaoHandel += new Baby().Cry; miaoHandel += new Mother().Awake; //还可以通过-=来删除方法 miaoHandel -= new Mother().Awake; miaoHandel.Invoke(); } Console.ReadLine(); } }
说到这儿,那么到底什么是事件呢?
其实前面我讲了委托是一个类,那么事件就是委托的一个实例,加了一个event关键字。
那要说委托与事件的区别。本质上就是类跟实例的区别了。
来我们还是来看看代码
先在Cat类定义一个事件
1 //这里定义一个委托 2 public delegate void MiaoHandel(); 3 4 ///5 /// 猫类 6 /// 7 public class Cat 8 { 9 /// 10 /// 猫叫的方法 11 /// 12 public void Miao() 13 { 14 Console.WriteLine("猫喵了一声"); 15 } 16 17 public event MiaoHandel MiaoHandelEvent; 18 }
主程序里面就用我们自己定义的委托的实例(事件)来调用
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 { 6 //直接调用 7 new Cat().Miao(); 8 } 9 Console.WriteLine("--------------------------------"); 10 { 11 //用委托来调用 12 Cat cat = new Cat(); 13 cat.MiaoHandelEvent = new MiaoHandel(new Cat().Miao); //报错了:这里不能直接赋值 14 cat.MiaoHandelEvent += new Mouse().Run; 15 cat.MiaoHandelEvent += new Baby().Cry; 16 cat.MiaoHandelEvent += new Mother().Awake; 17 //还可以通过-=来删除方法 18 cat.MiaoHandelEvent -= new Mother().Awake; 19 cat.MiaoHandelEvent.Invoke(); //报错了:这里不能直接赋 20 } 21 Console.ReadLine(); 22 } 23 }
改成事件之后 ,我们会发现 事件是不能被赋值和调用的,这样做的好处就是 出于安全性的考虑,可以控制权限,外面不能赋值/调用。
那么要使用事件就必须在这个事件的发起者内部定义调用的方法。再来看看 修改之后最终的代码
猫类的方法
1 namespace DelegateEventDemo 2 { 3 //这里定义一个委托 4 public delegate void MiaoHandel(); 5 6 ///7 /// 猫类 8 /// 9 public class Cat 10 { 11 /// 12 /// 猫叫的方法 13 /// 14 public void Miao() 15 { 16 Console.WriteLine("猫喵了一声"); 17 } 18 19 public event MiaoHandel MiaoHandelEvent; 20 21 /// 22 /// 事件的调用方法 23 /// 24 public void MiaoHandelEventInvoke() 25 { 26 if (this.MiaoHandelEvent != null) 27 { 28 MiaoHandelEvent.Invoke(); 29 } 30 } 31 } 32 }
最终调用
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 { 6 //直接调用 7 new Cat().Miao(); 8 } 9 Console.WriteLine("--------------------------------"); 10 { 11 //用委托来调用 12 Cat cat = new Cat(); 13 cat.MiaoHandelEvent += new Cat().Miao; 14 cat.MiaoHandelEvent += new Mouse().Run; 15 cat.MiaoHandelEvent += new Baby().Cry; 16 cat.MiaoHandelEvent += new Mother().Awake; 17 18 cat.MiaoHandelEventInvoke(); 19 } 20 Console.ReadLine(); 21 } 22 }
总结
委托与事件的区别:
1. 委托是一个类型,事件就是委托的一个具体实例,加上一个event关键字
2. 委托可以直接赋值和调用。而事件不能直接被赋值和调用, 这是出于安全性的考虑。