第4部分 类型设计-----《Microsoft.NET框架程序设计》

18 篇文章 0 订阅

    有时我们会感到编译器自动产生的add和remove方法不够理想.例如,如果我们需要频繁地添加或者移除委托实例,同时我们又知道我们的应用程序是在单线程环境下运行,这时再对包含委托实例的对象进行同步访问的话就会损伤应用程序的性能.

    另外,如果我们的类型定义了许多事件,那么我们也会对编译器自动产生的add和remove方法感到不够满意.

     幸运的是,C#和许多其他的编译器都允许我们显式实现add和remove访问器方法.下面的示例对前面MailManager类型进行了修改,为add和remove访问器方法提供了显式实现.

    class MailManager  {

            //1.传递给事件接受者的类型定义信息

            public class MailMsgEventArgs  :  EventArgs  {...}

            //2.下面的委托类型定义了接受者必须实现的回调方法原型

            public delegate void MailMsgEventHandler (Object sender, MailMsgEventArgs args);

            //3a.显式定义一个私有委托链表字段

            private MailMsgEventHandler mailMsgEventHandlerDelegate;

            //3b.显式定义事件及其访问器方法

           public event  MailMsgEventHandler  MailMsg  {

                   //将传入的事件处理器(value)添加到委托链表上

              add   {

                            mailMsgEventHandlerDelegate=(MailMsgEventHandler)Delegate.Combine(mailMsgEventHandlerDelegate,value);

                            }

                        //将传入的事件处理器(value)从委托链表上移除

                        remove  {

                                              mailMsgEventHandlerDelegate=(MailMsgEventHandler)Delegate.Remove(mailMsgEventHandlerDelegate,value);

                                   }

                             //4.下面的受保护虚方法负责通知事件的登记对象

                            protected   virtual void OnMailMsg(MailMsgEventArgs e)    {

                             //有对象登记事件吗?

                            if(mailMsgEventHandlerDelegate!=null)  {

                            //如果有,则通知委托链表上的所有对象

                              mailMsgEventHandlerDelegate(this,e);

                             }

               }

               //5.下面的方法将输入转化为期望的事件,该方法在新的电子邮件消息到达时被调用

               public void SimulateArrivingMsg(String from, String to,String subject, String body )  {...}

              在新版的MailManager中,第1、2、5步和前面示例中的完全相同, 没有做任何改变,第3步被分成了两步(3a和3b),第4步有一些小的改动.下面我们来详细分析这些改动。

               3a.显式定义了一个私有委托链表字段

               在先前的示例中,C#编译器会自动为我们定义一个私有字段.在新版的示例中,我们使用了另外一种定义事件的语法,我们不仅要显式提供add和remove访问器方法的实现,我们还要显式提供一个保存委托链表的字段.

              3b显式定义事件及其访问器方法

              第3a步中只是定义了一个字段(一个MailMsgEventHandler委托实例).该字段还不能成为一个事件成员.新的事件语法实际上就是代码中定义事件成员的内容,其中的add和remove块为事件的访问器方法提供了实现.注意,每个访问器方法都接受一个类型为MailMsgEventHandler的隐含参数(value).这些方法在内部或者向委托链表上添加一个MailMsgEventHandler委托实例,或者从委托链表上移除一个MailMsgEvent Handler委托实例.我们知道属性可以有一个get访问器方法,也可以有一个set访问器方法,还可以同时拥有get和set两个访问器方法.但是事件必须同时具有add访问器方法和remove访问器方法.

    上面的示例除了没有应用MethodImplAttribute特性外,其他地方和C#编译器自动产生的代码的行为非常类似.实际上,我们仍然可以在源代码中使用+=操作符和-=操作符,编译器遇到她们时会去自动调用我们显式实现的方法.MethodImplAttribute特性的缺失使得上述示例实现的访问器方法不再是线程安全的方法,但是这意味着代码的性能将有所提升.当然,只有在我们确信每次只有一个线程访问事件的委托链表时,我们才应该移除MethodImplAttribute特性.

   4.定义一个受保护的虚方法,负责通知事件的登记对象

   从语义上来讲,这里的OnMailMsg方法和前一个版本的OnMailMsg方法是相同的.二者唯一的差别是我们将事件成员的名称替换成了委托字段的名称.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值