委托的应用之事件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了委托的应用之事件相关的知识,希望对你有一定的参考价值。

前言

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

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

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

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

 1     /// <summary>
 2     /// 猫类
 3     /// </summary>
 4     public class Cat
 5     {      
 6         /// <summary>
 7         /// 猫叫的方法
 8         /// </summary>
 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     /// <summary>
21     /// 老鼠类
22     /// </summary>
23     public class Mouse
24     {
25         /// <summary>
26         /// 老鼠跑的方法
27         /// </summary>
28         public void Run()
29         {
30             Console.WriteLine("老鼠开始跑");
31         }
32     }
33 
34    /// <summary>
35     /// 小孩类
36     /// </summary>
37     public class Baby
38     {
39         /// <summary>
40         /// 小孩哭的方法
41         /// </summary>
42         public void Cry()
43         {
44             Console.WriteLine("婴儿哭了起来");
45         }
46     }
47 
48     /// <summary>
49     /// 妈妈类
50     /// </summary>
51     public class Mother
52     {
53         /// <summary>
54         /// 妈妈醒的方法
55         /// </summary>
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     /// <summary>
 5     /// 猫类
 6     /// </summary>
 7     public class Cat
 8     {      
 9         /// <summary>
10         /// 猫叫的方法
11         /// </summary>
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     /// <summary>
 5     /// 猫类
 6     /// </summary>
 7     public class Cat
 8     {      
 9         /// <summary>
10         /// 猫叫的方法
11         /// </summary>
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     /// <summary>
 7     /// 猫类
 8     /// </summary>
 9     public class Cat
10     {      
11         /// <summary>
12         /// 猫叫的方法
13         /// </summary>
14         public void Miao()
15         {
16             Console.WriteLine("猫喵了一声");
17         }
18 
19         public event MiaoHandel MiaoHandelEvent;
20 
21         /// <summary>
22         /// 事件的调用方法
23         /// </summary>
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. 委托可以直接赋值和调用。而事件不能直接被赋值和调用, 这是出于安全性的考虑。

 

以上是关于委托的应用之事件的主要内容,如果未能解决你的问题,请参考以下文章

js事件流之事件冒泡的应用----事件委托

C#编程之委托与事件四

《C#零基础入门之百识百例》(七十八)委托事件实例练习3 -- 观察者模式

C#基础知识之事件和委托

至今最大之敌:委托和事件(重中之重)

C#和ASP.NET之事件