博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
分分钟用上C#中的委托和事件
阅读量:4116 次
发布时间:2019-05-25

本文共 6497 字,大约阅读时间需要 21 分钟。

每一个初学C#的程序猿,在刚刚碰到委托和事件的概念时,估计都是望而却步,茫然摸不到头脑的。百度一搜,关于概念介绍的文章大把大把的,当然也不乏深入浅出的好文章。可看完这些文章,大多数新手,估计也只是信心满满的觉得自己看懂了,一旦要在自己的程序中用上委托和事件,就傻眼了,根本不知道什么情况下该用,也不知道具体怎么用。

本文没有任何概念介绍,旨在帮助同学们快速用上委托和事件,进入C#的更高境界。

  • 首先,我们需要知道,到底在什么情况下必须使用委托和事件呢?

请看下面的场景:首领A要搞一场鸿门宴,吩咐部下B和C各自带队埋伏在屏风两侧,约定以杯为令:若左手举杯,则B带队杀出;若右手举杯,则C带队杀出;若直接摔杯,则B和C同时杀出。B和C袭击的具体方法,首领A并不关心。(完整代码在全文最后。)

有脑子反应快的同学,马上说,这个逻辑,用一个IF条件判断语句不就搞定了吗:

复制代码

1 if(左手举杯) 2 { 3   B带队杀出;   4 } 5 else if(右手举杯) 6 { 7   C带队杀出;   8 } 9 else if(直接摔杯)10 {11   B带队杀出;12   C带队杀出;  13 }14 else15 {16   按兵不动  17 }

复制代码

如果真这么简单,那我还写这篇文章干嘛呢。请这位同学认真想想:首领A会什么时候发出信号呢?估计连他自己都不知道。那么上面这段伪码,你打算插入到哪里呢?难道B和C就一直不停的用While循环做上述判断吗?显然不合适吧。更重要的,如果扩展一下,部下不止B和C,而是B、C、D、E等等,每个人都有自己不同的响应领导号召的方法,那么对首领A而言,要分别去跟每个部下打交道,上述的伪码,会进行无尽的扩展和完善,显然也不是我们所希望的。

正确的逻辑应该是,B和C不管宴席上发生的任何其他事情,只等首领发出举杯或者摔杯的信号,一旦首领A发出信号,相当于通知了所有部下,凡是约定好的部下,都立马各自行动!

我们定义三个类,分别模拟首领A和部下B、C:

复制代码

///     /// 首领A    ///     public class A    {         }    ///     /// 部下B    ///     public class B    {         }    ///     /// 部下C    ///     public class C    {         }

复制代码

首领A的类有举杯和摔杯两种方法,其中,举杯方法带有一个形参,用于传递是左手举杯,还是右手举杯。部下B和C的类,各自有一种攻击方法。

复制代码

///     /// 首领A    ///     public class A    {        ///         /// 举杯        ///         /// 手:左、右        public void Raise(string hand)        {            Console.WriteLine("首领A{0}手举杯", hand);        }        ///         /// 摔杯        ///         public void Fall()        {            Console.WriteLine("首领A摔杯");        }    }    ///     /// 部下B    ///     public class B    {        ///         /// 攻击        ///         public void Attack()        {            Console.WriteLine("部下B发起攻击");        }    }    ///     /// 部下C    ///     public class C    {        ///         /// 攻击        ///         public void Attack()        {            Console.WriteLine("部下C发起攻击");        }    }

复制代码

至此,三个独立的类,构造完毕。那么,怎么让部下B和C,根据首领的暗语才去相应的行动呢?

我们需要在首领A类中,采用一种方法,把其意图传递出去。在首领A类之前,分别定义一个带形参的举杯委托RaiseEventHandler和一个不带形参的摔杯委托FallEventHandler。命名规则是在准备传递的方法名后加上EventHandler,不要问我为什么,介绍为什么的文章多得是,大家大可以去查阅。本文的宗旨是,教会大家如何快速的使用委托和事件。当然,你也可以不遵循此命名规则,对程序的运行没有任何影响,只是会增加自己或他人日后阅读代码的难度。

delegate void RaiseEventHandler(string hand);delegate void FallEventHandler();

然后,在首领A类中,定义两个事件。这个类似于大家在WinForm中拖放一个Button后,双击该Button,即可编辑其事件。

复制代码

///         /// 首领A举杯事件        ///         public event RaiseEventHandler RaiseEvent;        ///         /// 首领A摔杯事件        ///         public event FallEventHandler FallEvent;

复制代码

好了,做完上面两个步骤后,就可以在首领A的举杯和摔杯方法中,调用上述两个事件了。这样,如果B和C中订阅该事件,便可自动执行了。

复制代码

///         /// 举杯        ///         /// 手:左、右        public void Raise(string hand)        {            Console.WriteLine("首领A{0}手举杯", hand);            // 调用举杯事件,传入左或右手作为参数            if (RaiseEvent!=null)            {                RaiseEvent(hand);            }        }        ///         /// 摔杯        ///         public void Fall()        {            Console.WriteLine("首领A摔杯");            // 调用摔杯事件            if (FallEvent!=null)            {                FallEvent();            }        }

复制代码

同样,不要问为什么这样写。按照上述操作即可。一旦用熟这种方法,体会其中含义,自然就明白为何这么写了。

在部下B和C心中,必须存在首领A,才能执行A的暗示吧。所以,在B类和C类中,需要声明一个A,该声明可以通过B和C的构造函数进行实例化。实例化之后,便可在类B和类C中订阅类A的事件了。

完整代码如下:

复制代码

1     class Program  2     {  3         static void Main(string[] args)  4         {  5             A a = new A(); // 定义首领A  6   7             B b = new B(a); // 定义部下B  8   9             C c = new C(a); // 定义部下C 10  11             // 首领A左手举杯 12             a.Raise("左"); 13  14             // 首领A右手举杯 15             //a.Raise("右"); 16  17             // 首领A摔杯 18             //a.Fall(); 19  20             Console.ReadLine(); 21             // 由于B和C订阅了A的事件,所以无需任何代码,B和C均会按照约定进行动作。 22         } 23     } 24  25     ///  26     /// 首领A举杯委托 27     ///  28     /// 手:左、右 29     public delegate void RaiseEventHandler(string hand); 30     ///  31     /// 首领A摔杯委托 32     ///  33     public delegate void FallEventHandler(); 34     ///  35     /// 首领A 36     ///  37     public class A 38     { 39         ///  40         /// 首领A举杯事件 41         ///  42         public event RaiseEventHandler RaiseEvent; 43         ///  44         /// 首领A摔杯事件 45         ///  46         public event FallEventHandler FallEvent; 47  48         ///  49         /// 举杯 50         ///  51         /// 手:左、右 52         public void Raise(string hand) 53         { 54             Console.WriteLine("首领A{0}手举杯", hand); 55             // 调用举杯事件,传入左或右手作为参数 56             if (RaiseEvent!=null) 57             { 58                 RaiseEvent(hand); 59             } 60         } 61         ///  62         /// 摔杯 63         ///  64         public void Fall() 65         { 66             Console.WriteLine("首领A摔杯"); 67             // 调用摔杯事件 68             if (FallEvent!=null) 69             { 70                 FallEvent(); 71             } 72         } 73     } 74     ///  75     /// 部下B 76     ///  77     public class B 78     { 79         A a; 80  81         public B(A a) 82         { 83             this.a = a; 84             a.RaiseEvent += new RaiseEventHandler(a_RaiseEvent); // 订阅举杯事件 85             a.FallEvent += new FallEventHandler(a_FallEvent); // 订阅摔杯事件 86         } 87         ///  88         /// 首领举杯时的动作 89         ///  90         /// 若首领A左手举杯,则B攻击 91         void a_RaiseEvent(string hand) 92         { 93             if (hand.Equals("左")) 94             { 95                 Attack(); 96             } 97         } 98  99         /// 100         /// 首领摔杯时的动作101         /// 102         void a_FallEvent()103         {104             Attack();105         }106 107         /// 108         /// 攻击109         /// 110         public void Attack()111         {112             Console.WriteLine("部下B发起攻击,大喊:猛人张飞来也!");113         }114     }115     /// 116     /// 部下C117     /// 118     public class C119     {120         A a;121         public C(A a)122         {123             this.a = a;124             a.RaiseEvent += new RaiseEventHandler(a_RaiseEvent); // 订阅举杯事件125             a.FallEvent += new FallEventHandler(a_FallEvent); // 订阅摔杯事件126         }127         /// 128         /// 首领举杯时的动作129         /// 130         /// 若首领A右手举杯,则攻击131         void a_RaiseEvent(string hand)132         {133             if (hand.Equals("右"))134             {135                 Attack();136             }137         }138 139         /// 140         /// 首领摔杯时的动作141         /// 142         void a_FallEvent()143         {144             Attack();145         }146         /// 147         /// 攻击148         /// 149         public void Attack()150         {151             Console.WriteLine("部下C发起攻击,一套落英神掌打得虎虎生威~");152         }153     }

复制代码

转载地址:http://tnupi.baihongyu.com/

你可能感兴趣的文章
关于无线PCB中 中50欧姆的特性阻抗的注意事项
查看>>
Spring的单例模式源码小窥
查看>>
后台服务的变慢排查思路(轻量级应用服务器中测试)
查看>>
MySQL中InnoDB事务的默认隔离级别测试
查看>>
微服务的注册与发现
查看>>
bash: service: command not found
查看>>
linux Crontab 使用 --定时任务
查看>>
shell编程----目录操作(文件夹)
查看>>
机器学习-----K近邻算法
查看>>
HBASE安装和简单测试
查看>>
关于程序员的59条搞笑但却真实无比的编程语录
查看>>
搞笑--一篇有趣的文章编译自一篇西班牙博客。有一位美丽的公主,被关押在一个城堡中最高的塔上,一条凶恶的巨龙看守着她,需要有一位勇士营救她…
查看>>
非常不错 Hadoop 的HDFS (Hadoop集群(第8期)_HDFS初探之旅)
查看>>
Tomcat启动错误,端口占用
查看>>
laravel 修改api返回默认的异常处理
查看>>
高德坐标转换百度坐标 javascript
查看>>
tp5封装通用的修改某列值
查看>>
laravel控制器与模型名称不统一
查看>>
vue登录拦截
查看>>
npm配置淘宝镜像仓库以及electron镜像
查看>>