关于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中对于委托的示例

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

附上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案例.

      应用实例:

《关于C#中的委托与事件以及两者之间的关系》 图1
《关于C#中的委托与事件以及两者之间的关系》 图2
《关于C#中的委托与事件以及两者之间的关系》 图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(删除订阅)的方法.以便于事件更为便携的添加和删除一些委托中的操作.

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

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

    原文作者:SharaYuki
    原文地址: https://www.jianshu.com/p/07f87e7eaac7
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞