浅谈事件与委托

先看看某大牛举了一个下雨打电话给邻居收衣服的例子,感觉似乎瞬间开朗!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 收衣服
{
    public delegate void Mydelegate();   //先定义一个委托类

    class me   //我
    {
        public void PickupClothes()   //我有一个收衣服的方法
        {
            Console.WriteLine("衣服收好了!");
        }
        public void PhoneNeighbor()   //我还有一个给邻居打电话的方法
        {
            Neighbor PLMM = new Neighbor();    //假设邻居是一个漂亮MM~
            PLMM.GetPhone += new Mydelegate(PickupClothes);    //告诉她怎么收衣服。。。(给getphone事件绑定一个pickupclothes的方法)
            PLMM.Doit();   //just do it...
        }
    }
    class Neighbor   //邻居
    {
        public event Mydelegate GetPhone;   //邻居有一个接电话的事件
        public void Doit()    //邻居还要有一个能处理事件的方法
        {
            if (GetPhone != null)    //如果我打电话过来不是啥都没说
            {
                GetPhone();    //那么就照我说的去做吧!
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("下雨了!");    //下雨了。。。
            me me = new me();     //实例化一个我
            me.PhoneNeighbor();    //给邻居打电话
        }
    }
}

 

专家说:

你的“例子”看似没有太多问题,但是我想可能是你没有明确表示你的习惯的应用而已。

比如说我们把一个地图放入我们的程序窗口中,然后在这个地图上标注我们自己所关心的旅行日程和路线。那么地图处理有关标注的行为(真因为它有了这个能力所以我们才把它作为服务而引入我们的程序),我们的程序随时可能收到有关“用户标注”的行为通知。而不是你所写的什么“JustDo”。

记住,不是你去Do那么PLMM,而是她Do你,你然后在事件处理过程结束后把返回参数返回给她。不是你Do她,是她Do你!

按照你的写法,结合上面的地图标注程序,那么你的理解就类似于说,当我们的程序想去捕获用户自由地在地图上标注旅行日程路线行为时,我们“去调用地图服务的一个方法”,于是这个方法就挂起了所有程序,然后用户就进行一系列标注行为,然后我们调用的这个地图方法返回给程序标注行为结果。但是交互式程序根本不是这样设计的!你不可能调用地图的类似于计算的方法那样用“输入-输出”的方式设计。

你的代码有这种倾向。如果你这样设计交互程序流程,那么你做不出稍微流畅一点的交互程序。你需要重新学会程序设计。
 
 
 

大多数时候,我们使用服务,不是我们去要给她什么“收衣服”的指令来命令她。对方凭什么只有那一个空洞的行为呢?对方其实有完整、丰富的行为,她暴露出少量的事件接口,她饿了我们带她出去吃饭,她累了我们给她锤锤腿,她困了我们给她讲随眠的编程技术术语.....我们监听对方的行为,不是因为对方只有你的代码所表现的那么简单的内涵。我们使用一个服务、注册监听其事件,是因为它会随时主动发出各种丰富行为的事件通知,然后我们对这种事件通知进行处理、并把事件参数进行必要的修改(这样服务就能收到反馈)。

而你的例子,虽然代码上没有很大问题,但是你设计事件时很可能容易存在“简单化、滥用”的危险。

 

回调,这是很基本的编程。自从有(机器语言和汇编语言)编程就有这个回调机制,例如在汇编语言的大型程序中总是有“调用表”去将不同层次的系统分层,底层就是使用表格驱动方式来回调高层次的代码的。再比如硬软件结合的机器中断——软件回调机制。自从有windows开始微软的编程工具中一直又有事件驱动的机制。事件是驱动程序开发的基本机制,不懂事件驱动就会产生很多繁琐的所谓“设计模式”,或者诡异的所谓“注入方法”。

假设a依赖于b,a作为客户而b作为服务,那么如果b有些消息要通知ajiu可以使用事件通知。例如TextBox控件是在你的程序之前开发的,你的控件要扩展TextBox控件实例的功能,就是去注册此TextBox控件的回调处理方法,这就可以扩展它的功能。

并且可有很多客户程序去注册同一个服务的同一个事件处理,服务会轮询调用这些方法。

但是人家TextBox实现在需要通知自己的客户的地方定一个委托事件接口,所以你可以注册它可以调用的处理方法。但是事件接口是强类型的,客户只能在服务开放回调的地方去注册事件处理方法。如果它允许随意注入的话,客户端就会随意修改它,所以事件机制当然比AOP可靠很多。

这是编程设计的基本机制。

事件是驱动程序开发的基本机制 --> 事件是windows系程序开发的基本机制

 

委托就是一个指向方法的变量,事件就是指向委托的变量,

 

------------------------------------------------------------------------------------

委托:
  一种变量类型,这个变量类型叫委托
  
事件:
  用这个变量类型实例化一个变量, 这个变量就是事件,


好比:
  如我用 int 表是 方法类型,
那:
  List<int>
就是委托。

而:
  List<int> ev 
中的 ev 就是事件,
  ev 是可以有add方法的, 这相当于,事件注册,  
  remove 方法 相当于取消注册
   
  要有执行事件时 ,只要 ev(); 就行了,----相当于用foreach 编历ev ,对它每个无素调用。
 

当然方法类型不是我上面这样声时的,
  就是如下:
如有方法
public void doSomethings(object sender, EventArgs e)
{}
如下声明 委托,----就是上面这个方法类型

    public delegate void 委托_上面的方法的类型(object sender, EventArgs e);

    委托_上面的方法的类型 //就是方法类型



 

public event 委托_上面的方法的类型 ev;
 中的ev 就是事件了。


如下注册

ev+=new bk(doSomethings);//注册方事件,就是说这个事件变量被它的管理者调用时,就会执行它注册的方法,参数照样传,只是没有返回值。


 

 

                                                                        以上部分内容来自论坛

                                                                        整理:段利庆

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值