当前位置: 移动技术网 > IT编程>开发语言>.net > 【C#进阶】委托那些事儿(二)

【C#进阶】委托那些事儿(二)

2019年03月07日  | 移动技术网IT编程  | 我要评论

一心一意的近义词,李铭筱微博,四不放过

二、传统的委托

  接下来讲一讲方法参数。下面以“餐馆服务员为客户下单”[2]的事件作为描述。一般对事件的做法分3个部分:

  1. 方法参数 eventargs,一般用于传送数据。在本例场景中

public delegate void ordereventhandler(customer cus, ordereventargs e);

public class ordereventargs : eventargs    // 习惯把xxeventargs 继承于c#自带的eventargs
{
    public string dishname { get; set;}    // 菜名
    public string size { get; set;}        // 份量
}

 

  2 . 触发事件的对象

  // 下单的事件是customer对象拥有的,∴写在customer类当中

public class customer
{
    private ordereventhandler ordereventhandler;
    public event ordereventhandler order {              // event类型是用来操作“方法类”这个盒子的
        add { this.ordereventhandler += value;}         // add是事件处理器的添加器
        remove { this.ordereventhandler -= value;}
    }

    public void thinkfororder ()                        // 顾客下单
    {
         if (this.ordereventhandler != null )
         {  
               ordereventargs e = new ordereventargs{ dishname = "soup", size = "large"};
               this.ordereventhandler.invoke(this, e);  // this指此类实例化的customer
         }
    }
}

 

  3 . 执行的方法

  在主函数中,为customer对象的order事件订阅waiter.action,客户的下单,需要由服务员行动。

  cus.order += waiter.action;

  即有:

        public class waiter

        { public void action(customer cus, ordereventargs e) { ... }  }

  总结上文:

main

       customer cus = new customer();

       waiter wai = new waiter();

       cus.order += wai.action;

       cus.thinkfororder();

       console.writeline("the customer will pay {0}.", cus.billprice);

customer

 

事件对象对eventhandler方法类的订阅

waiter

    public class waiter

    {

        internal void action(customer customer, ordereventargs e)       // internal可改为public

        {

            console.writeline("waiter will serve mr.{0} {1}." , customer.name, e.dishname);

            customer.bill += e.price;

        }

    }

 

三、小结

  如果把事件写成委托型字段的话:

  -  假设有一客人badguy,并且badguy.order += waiter.action;,那么如果badguy.order.invoke(),即会破坏参数e,或者参数customer。

     例如,badguy不给自己点菜,点到了customera上,badguy.order.invoke(cus, e2);

  

  事件:

  -     使逻辑、对象关系更加安全,防止“借刀杀人”。

  -      只能写在+=或-=的左边。避免了委托被直接invoke调用。

    (委托字段可能在public当中被滥用,所以微软推出event这种成员。)

  -      本质:委托字段的包装器;

                   对委托字段的访问仅起限制作用,仅暴露add、remove事件处理器的功能。

 

  -      参数:一个表示发送者,e表示发送的消息/数据/内容

  -      规定:事件触发必须由事件foo拥有者自己去发送信息。

       触发事件的方法一般命名为:onfoo,意为事出有因。

    注意:onfoo的访问级别一定是protected,若为public又可“借刀杀人”了。

 

  首尾呼应:

  属性不是字段——很多时候,属性是字段的包装器,保护字段不被滥用。包装器永远不可能是包装的东西。

 

注释:

[1] 自《深入理解c#》(第3版)jon skeet 著  姚琪琳 译

[2] 自刘猛铁的c#学习视频

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网