码迷,mamicode.com
首页 > 其他好文 > 详细

委托与事件

时间:2015-10-19 09:26:18      阅读:323      评论:0      收藏:0      [点我收藏+]

标签:

委托

 定义委托的语法和定义方法比较相似,只是比方法多了一个关键字delegate ,我们都知道方法就是将类型参数化,所谓的类型参数化就是说该方法接受一个参数,而该参数是某种类型的参数,比如int、string等等;而委托是将方 法参数化,说了上面的那个类型参数化之后,相信你也能猜到方法参数化的意思了,对,就是将方法作为一个参数传到一个委托中。

首先来看看声明委托的语句:

public deletate void MyDelegate();  

public:访问修饰符  delegate:关键字  void:返回类型  MyDelegate:委托名称  ( ):参数列表  

 

看到声明大家会想了,为什么该委托的返回值,参数列表要这样的,我不能返回一个 string,一个int么?我不能给委托加几个参数么? 答案是:当然可以,但委托的定义是相对于方法来说的,因为得你的委托最终是要来注册方法的,而你的方法是具有某种签名的,所以你要给怎样签名的方法来声明 一个委托,该委托就要和该方法具有同等的签名,就类似于你用一个int 类型的变量去接受一个string类型的值,显然是不行的(个人理解).... 

 * 委托只要定义就可以了,我们并不需要关心他的实现  

 

委托的使用

注册委托有两种方法:

第一种:直接将方法赋值[=]或者用“+=” 给一个委托==>委托名 =[+=]  方法名 

第二种:委托本质也是一个类,只是一个特殊的类,所以我们也可以实例化一个委托对象通过委托构造函数来注册委托==》委托名 对象名= new 委托名(方法名) 

 

 了解了委托的声明和使用,我们就可以来看小例子来加深理解了

 首先看看界面: 

 技术分享

界面上就是简单的四个按钮 两个属于委托,两个属于事件,都是一个用来执行,一个用来干扰,以便于来理解委托事件

然后看后台代码,首先我定义了一个Test类,声明委托,实例了委托,还声明了事件,写了个方法用来触发事件,代码如下: 

Test类 1     public class Test
    {
        //声明一个委托
        public delegate void MyDelegate();

        //创建一个委托实例
        public MyDelegate myDel;
        //声明一个事件
        public event MyDelegate EventMyDel;

        //事件触发机制(必须和事件在同一个类中) 外界无法直接用EventMyDel()来触发事件
        public void DoEventMyDel()
        {
            EventMyDel();            
        }    
    }
方法 1         //方法A
        public void Fun_A()
        {
            MessageBox.Show("A 方法触发了");
        }

        //方法B
        public void Fun_B()
        {
            MessageBox.Show("B 方法触发了");
        }
        //方法C
        public void Fun_C()
        {
            MessageBox.Show("C 方法触发了");
        }

  

Page_Load 1        //页面载入事件
        private void Form1_Load(object sender, EventArgs e)
        {
            
           //注册委托(挂载方法)
           test.myDel += Fun_A;
           test.myDel += Fun_B;

           //注册事件(挂载方法)
           //test.EventMyDel += Fun_A;
           //test.EventMyDel += Fun_B;
        }

  

执行委托按钮事件1        //执行委托
        private void button1_Click(object sender, EventArgs e)
        {
            //执行委托链中的方法
            test.myDel();
        }

  

显示效果:

 技术分享  技术分享

 

说明没问题,方法都挂载到委托链上了,但是如果这时候我们来进行下干扰呢?各位想想看,结果会是怎么样了呢,先贴上干扰的代码:
委托干扰代码1       //委托干扰事件
        private void button2_Click(object sender, EventArgs e)
        {
            //给委托赋 null 值
            test.myDel = null;

            //给委托挂载上C方法
            test.myDel += Fun_C;

  

事件

事件就是一个特殊的委托,委托和事件就类似于字段和属性的关系,事件是对委托做了一个封装(这是个人理解)

先看看声明一个事件:

public Event MyDelegate EventMyDel;

public:访问修饰符  Event:关键字 MyDelegate:委托 EventMyDel:事件名称

 

接下来让我们来看看我们用反编译工具来反编译下该项目的exe可执行文件,看看当我们给事件注册上方法时,事件内部在做什么,附上反编译代码:

技术分享

从 反编译中就可以充分看出,事件的本质就是一个委托,它的内部仍然是用一个委托,该委托的名称的方法就只有和事件名首字母的大小写不同而已,该委托来负责接 收事件,然后通过add,remove方法来实现委托的注册和删除,即当我们给委托注册一个方法时,内部就调用add方法,通过 Delegate.Combine()方法来实现将方法附加到委托链上,当我们删除委托链上的一个方法时,即内部调用remove方法,通过Delegate.Remove()方法,将该方法从委托链上移除,所以通过反编译工具,我们就可以清楚的知道事件内部的实现代码了。

接下来看看事件的效果,首先在Page_Load事件中注册事件,我们将A,B方法注册到事件上,代码如下:

页面载入 1        //页面载入事件
        private void Form1_Load(object sender, EventArgs e)
        {
            
           ////注册委托(挂载事件)
           //test.myDel += Fun_A;
           //test.myDel += Fun_B;

           //注册事件
            test.EventMyDel += Fun_A;
            test.EventMyDel += Fun_B;
        }

  

执行事件1        //执行事件
        private void button3_Click(object sender, EventArgs e)
        {
            //执行事件触发方法
            test.DoEventMyDel();
        }

  

看看效果,如图:

 技术分享技术分享

 

 

和刚开始的委托一样,没有问题,两个方法都触发了,接下来再让我们来实施干扰,附上干扰代码:
技术分享
1        //干扰事件
2         private void button4_Click(object sender, EventArgs e)
3         {
4             //注册干扰事件
5             test.EventMyDel = null;
6        
View Code

慢着,,此时编译报错了,报了什么错呢,,我们看看:

技术分享

说明了什么,,说明我们没法对事件用赋值[=]号来进行注册,这就避免了破坏直接委托链的指针指向了,,但你会想了,那如果我们用附加[+=]上一个null对象呢?会干扰到么??好的,,我们实施下,修改代码,如下:

技术分享
修改干扰事件 1         //干扰事件
        private void button4_Click(object sender, EventArgs e)
        {
            //注册干扰事件
            test.EventMyDel += null;

            //注册C方法
            test.EventMyDel += Fun_C;

        }
View Code

运行如图:

技术分享 

 

运行结果如下:

 技术分享技术分享技术分享

 

所以没有问题,即使你附加了一个null对象,三个方法照样依次执行了,,这就是事件的封装效果了.......

 

委托与事件

标签:

原文地址:http://www.cnblogs.com/wswbk/p/4890917.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!