VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > c#教程 >
  • C#教程之C#教程之【C#进阶】委托那些事儿(二)

本站最新发布   C#从入门到精通
试听地址  
https://www.xin3721.com/eschool/CSharpxin3721/

二、传统的委托

  接下来讲一讲方法参数。下面以“餐馆服务员为客户下单”[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(customerA, e2);

  

  事件:

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

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

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

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

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

 

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

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

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

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

 

  首尾呼应:

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

 

相关教程