委托的应用之事件


前言

  上一个章节介绍了委托,这里我们再通过一个例子继续巩固一下委托并引入事件  。

  为了便于理解,这里还是引入一个很老的例子:

      因为一只猫叫了一声 接着老鼠被吓跑 小孩哭也了起来 最后妈妈也被吵醒。

      下面用代码来实现这些功能

 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. 委托可以直接赋值和调用。而事件不能直接被赋值和调用, 这是出于安全性的考虑。