关于C#中的委托与事件以及两者之间的关系

  一  关于委托

1.委托的概念:

    C# 中的委托(Delegate)是一种引用类型变量,它类似于C的函数指针,可以将方法当做参数的形式进行调用,将一个方法以变量的形式保存起来.我们一般在C#中使用委托来进行一种方法的传递或者回调.在Xamarin.iOS中为了解决代理中事件的传递,我们就可以通过C#的委托进行实现.

2.委托的声明:

    委托的声明格式非常简单.

     public|权限,可省略 delegate|委托关键字 return type|委托方法的返回值 name|委托名 (type1 name1,type2 name2,...)|委托方法的参数列表;

     例1:我要声明一个能携带返回值为void,无参方法的委托 delegate void MyDelegate ();

     例2:我要声明一个公开的能携带返回值为int,有两个int参数方法的委托: public delegate int MyDelegate(int num1,int num2);

3,委托的实例化:

      委托的实例化必须使用new关键字,并同时提供一个特定的方法,该方法的类型必须和你声明的委托一致,例如我要实例化以上声明例子2中的委托.

    public int sum(int num1,int num2){

        return num1+num2;

   }

     MyDelegate del = new MyDelegate(sum); 

4.委托使用的示例:

      这里给大家提供w3cschool中对于委托的示例

附上w3cschool对于委托介绍的原地址以表感谢:www.w3cschool.cn/csharp/csharp-delegate.html

  二  关于事件

写在前面:

     C#中关于事件的介绍有很多,并且关于事件存在的必要性,似乎设计者本身没有太多的考虑,至少我觉得事件能做到的事情,似乎委托也能做到,所以笔者一直很困惑,于是我查找了各种资料,但我个人觉得上面写的都不够直白难以理解,也或许是我才接触的原因,所以理解上有些困难,在我看了不下一周的各类资料后,觉得有必要写一篇自己的见解,希望能对同样才接触C#的新手有所帮助.

1.事件的概念:

     事件(Event)基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些出现,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断。事件是用于进程间通信。

     以上是w3cschool中对事件的说明.让我们再来看看官方对事件的介绍:

     类或对象可以通过事件向其他类或对象通知发生的相关事情。 发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为“订户”。

     在典型的 C# Windows 窗体或 Web 应用程序中,可订阅由按钮和列表框等控件引发的事件。 可以使用 Visual C# 集成的开发环境 (IDE) 来浏览控件发布的事件,并选择想要处理的事件。 IDE 将自动添加空白事件处理程序方法和订阅该事件的代码。 有关详细信息,请参阅如何:订阅和取消订阅事件

说了这么多巴拉巴拉一大堆的东西,我无非就总结出了这几点:

1.事件可以用在类与类之间消息传递.

2.发送事件的类是发送者,接收事件的类可以作为接受者,一个事件必须要这两个类.

3.事件可以用来进程之间通信

     其实然并卵,这些东西委托不就能做吗?我要这事件何用?先别着急,咱们一步步来!

2.事件的声明:

     事件的声明有两种方式,需要依托于委托的声明:

    1.隐式声明事件

     这种方式声明事件很简单,就如同声明委托实例一样:

     public|权限(可省略) event|关键字 Delegate|委托类型 name|事件名;

     例如:

     public void MyDelegate();

     public event MyDelegate evt;

     2.显式声明事件

     其实显式声明事件就是要自己来手动实现隐式声明事件的委托实例

和两个函数:

     例:

         public void MyDelegate();

         public MyDelegate _del;

         public event <委托类型|MyDelegate> evt

     {

                 add

             {

                //将函数注册到自己定义的委托实例

                _del = Delegate.Combine(_del, value) as MyDelegate;

             }

               remove

            {

                //解除函数对自己定义的委托实例的注册

                  _del = Delegate.Remove(_del, value) as MyDelegate;

             }

      }

注释:Delegate.Combine和Delegate.Remove是.net库函数,它是用于合并委托实例注册函数和移除委托实例注册函数并返回合并和移除后的委托实例,具体请查阅MSDN

3.事件的实例化:

     关于事件的实例化比较简单,其实和委托基本是一样的.

     例如:我要将上述例子中的事件实例化.

     public void test(){   

         Console.WriteLine("test");

     }

     evt = new MyDelegate(test);

     在.Net 2.0后可以通过简写的方法来实例化一个事件.

     evt = test;

     当然,你也可以通过添加订阅和删除订阅来为事件赋值.

     evt += new MyDelegate(test);

     evt -= new MyDelegate(test);

     添加订阅以及删除订阅实质上就是调用了add方法和remove方法,当然.Net 2.0后也支持简写方式.

     evt += test; evt -= test;

     附w3cschool对事件的讲解:www.w3cschool.cn/csharp/csharp-event.html

4.解决之前的疑惑:

      看了上述的介绍可以发现事件和委托实例是那么的相似,那么为什么不直接用委托还要用到事件呢?在解答之前我希望读者能先看一下我写的demo案例.

      应用实例:

图1
图2
图3

      该案例使用了纯委托和事件两种方式实现监听value值的变化,细心的读者可以发现,我在使用纯委托时候在Test类外声明了委托类型,Test类里声明了持有委托实例,为什么要两次声明?这就是关键点.测试发现在C#类里是无法通过委托类型去创建它的实例对象的,那么问题来了,如果不实例化,当我在一个类里如何发送消息给我的委托对象呢?所以我只能提前声明了委托对象后,再声明我持有该委托类型的对象,通过该对象去调用委托对象的方法!

      回到事件的声明这块,我们回顾一下事件的显式声明:

      public void MyDelegate();

      public MyDelegate _del;

      public event <委托类型|MyDelegate> evt    

     {

               add

         {

        //将函数注册到自己定义的委托实例

              _del = Delegate.Combine(_del, value) as MyDelegate;

        }

             remove

       {

        //解除函数对自己定义的委托实例的注册

             _del = Delegate.Remove(_del, value) as MyDelegate;

        }

    } 

    我们可以发现事件的显式声明其实给我们做了几件事:1.定义一个和事件同名的委托实例,2.手动实现add(订阅)和remove(删除订阅)的方法.以便于事件更为便携的添加和删除一些委托中的操作.

    也正是因此,在我上面的案例中,当我在类里声明了委托对应类型的事件后,不必去声明持有委托对应的实例,而是直接可以调用事件的操作,也能够去为其添加和删除订阅!

    这也就是为什么我们说事件是对委托进行的高度封装(笑~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容