换一个角度看.NET中的理解委托和事件

开发 后端
在.NET开发中,委托和事件是很让程序员们犯迷糊的一件事情。本文的作者或许能为大家提供另一条解决思路。

如果你还为委托和事件犯迷糊,你可以试着回答下面这些问题:让你来设计一个框架(或者程序)实现效果:点击button时实现label1.text=“呵呵,第一次点击!”,你会怎么处理?注意,不要用.net已经实现的框架。

我们会想,在windows系统里应该有一个监听程序,专门处理鼠标点击事件,一旦button被点击,他就会执行一定的程序。大概应该像下面的伪代码一样:

ListenerMethod(){
if(button.clicked)
{……}
}

我就可以在{}里写上label1.text=“呵呵,第一次点击”,搞定!如果要实现其他内容,比如再一次点击,就label.text=“没问题,第二次点击”。到此为止,你发现问题么?

如果还没有发现,呵呵,你就有问题了。

我也是在学习了“设计模式”之后才想到的,如果按上面的方法实现,就:

1、你必须把ListenerMethod()方法的具体内容公布出来,不然人家怎么用呢,这些执行的代码写在哪里呢

2、把方法公开是不好的,为什么?最简单的,怕人家看了干坏事呀,黑客是怎么出来的?呵呵,这其实只是一方面,更实际的原因甚至是防止自己误操作……不多说了,理解关键字“封装”!接着想,我要不把ListenerMethod()方法暴露出来要怎么办。可不可以事先写好一个方法,放在{}里,其他人在其他地方写实现的代码,如:

ListenerMethod(){
if(button.clicked){
TheMethod();  //只要按钮被点击就执行这个方法;
}
}

而在另外的地方设好方法名和参数,让其他人填空,如下

TheMethod(){
……//里面的内容由其他人(专业点的词汇叫做“用户”)填写
}

哈哈,有点像了。我们好像也是这样在buttonClick()方法里写实现程序的哟。

这样做,还是有问题,能不能想到?

现在我们是一个button,如果有两个button要实现各自不同的的功能呢,怎么办?我写两个if,哼!三个呢,四个呢……实际上,我做框架的时候还根本不知道会有多少个呢,唉~~再想!

这就要回到最前面猜想的地方了。button和Listener之间是不是要有对应关系?

这种对应关系如何实现?

我们可以想象,计算机系统里面有一个管理鼠标点击button的监听中心,每个button都可以到这个中心“注册登记”他对应的方法,这样,当特定的button被点击时,监听中心可以根据之前的“登记”,执行相应的方法。
看上去上面的方法不错,赞自己一个。那么如何实现上面的构想呢?当然就是用委托和事件了。

可能你还是没怎么搞明白,我也一样,那我们试着动手写程序吧。为了脱离winform之类已有的框架,我们建一个控制台程序。

未使用委托、事件之前的代码。

Code
class Program
    {
        static void Main(string[] args)
        {
            //实例化一个button类
            Button btn = new Button();
            btn.Click();
        }
    }

    //首先要定义一个Button类,里面应该有一个Click方法
    public class Button
    {
        //Click方法调用固定的方法
        public void Click()
        {
            ForCustome fc = new ForCustome();
            fc.Button_Click();
        }
    }
    //上面这个类是封装了的,用户不可见,或者理解为用户不能更改也可以

    //下面这个类提供给用户
    public class ForCustome
    {
        public void Button_Click()
        {
            //用户在这里写具体的方法实现
            Console.WriteLine("被点击了!");
        }

    }


可以看出,以上的代码实现一个按钮是可行的,但两个按钮就麻烦了。不到黄河心不甘,我们硬着头皮再写两个按钮的情况吧。

Code
    class Program
    {
        static void Main(string[] args)
        {
            //实例化一个button类
            Button btn = new Button();
            btn.Click();

            //实例化第二个button
            Button btn2 = new Button();
            btn.Click();   //这样写能行么?
        }
    }

    //首先要定义一个Button类,里面应该有一个Click方法
    public class Button
    {
        //Click方法调用固定的方法
        public void Click()
        {
            ForCustome fc = new ForCustome();
            fc.Button_Click();

            //很想在这里面改呀,添一个方法调用
            fc.Button2_Click();     //要是再有一段条件判断的逻辑就更好了,是吧?
        }
    }
    //上面这个类是封装了的,用户不可见,或者理解为用户不能更改也可以

    //下面这个类提供给用户
    public class ForCustome
    {
        public void Button_Click()
        {
            //用户在这里写具体的方法实现
            Console.WriteLine("被点击了!");
        }

        //添一个方法实现是必须的
        public void Button2_Click()
        {
            Console.WriteLine("我是第二个被点击的按钮!");
        }
    }

如果你是自己在试着写的话,估计你已经崩溃了(反正我是这样),不好办呀。如果看这段代码没有感觉的话,试着写一写。

好了,看看微软是如何解决这个问题的吧。

Code
    //先声明一个委托再说,目标是要能调用ForCustome类里的方法,所以注意方法签名
    public delegate void myDelegate();


    public class Button
    {
        //声明一个事件,和委托相关联
        public event myDelegate ClickIt;
       
        public void Click()
        {
            //可以想象,这个方法是一个封装了之前我们想要的一大段条件判断语句的“复合体”
            ClickIt();
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            ForCustome fc = new ForCustome();

            //实例化一个button类
            Button btn = new Button();
            //这里,将按钮的事件和按钮事件对应的(将要触发的)方法相关联,相当于我们之前想象的注册
            btn.ClickIt += new myDelegate(fc.Button_Click);
            btn.Click();

            //实例化第二个button
            Button btn2 = new Button();
            btn2.ClickIt+=new myDelegate(fc.Button2_Click);
            btn2.Click();   //这样写能行么?
        }
    }

    //这个类提供给用户的,没有变化
    public class ForCustome
    {
        public void Button_Click()
        {
            //用户在这里写具体的方法实现
            Console.WriteLine("被点击了!");
        }

        //添一个方法实现是必须的
        public void Button2_Click()
        {
            Console.WriteLine("我是第二个被点击的按钮!");
        }
    }

大功告成!欣赏一下吧,相当优雅的一个架构。如果还要再添加一个按钮和对应的事件,你会做了么?

而在Winform和ASP.NET中,给事件对应的方法添加了两个参数并规范了命名,就更完美了。

【编辑推荐】

  1. ASP.NET十个有效性能优化的方法
  2. 详解ASP.NET中Membership表和阻止DOS攻击
  3. 实战ASP.NET MVC帮助理解Routing
责任编辑:彭凡 来源: cnblogs
相关推荐

2021-12-14 17:19:15

存储数据

2017-03-06 15:05:57

2009-08-26 17:05:55

.NET委托

2009-08-18 11:08:24

.Net Framew

2011-06-16 15:14:17

VB.NET事件委托

2010-07-16 09:00:20

开源RedOffice红旗2000

2011-06-16 14:38:18

JavaScript事件委托

2009-08-20 18:11:08

C#异步委托

2016-09-14 21:28:25

JavaScript事件代理委托

2020-09-29 15:42:49

量子芯片网络

2022-07-28 08:34:59

事件委托JS

2021-03-29 13:00:50

代码替换开发

2021-05-10 07:35:11

SwaggeYApi部署

2009-08-03 13:23:04

C#编程组件-事件-委托

2009-08-18 10:54:17

C#事件和委托

2009-08-27 16:53:01

C#委托C#事件

2021-12-02 06:58:02

项目事件循环

2021-07-29 06:56:35

前端事件循环

2017-11-20 16:17:50

智慧城市

2009-08-06 10:58:55

jQuery和XAML
点赞
收藏

51CTO技术栈公众号