二、传统的委托

  接下来讲一讲方法参数。下面以“餐馆服务员为客户下单”[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又可“借刀杀人”了。

  首尾呼应:

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

注释:

[1] 自《深入理解C#》(第3版)Jon Skeet 著  姚琪琳 译

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

【C#进阶】委托那些事儿(二)的更多相关文章

  1. [.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门

    [.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门 本节导读: 认识表达式树(Expression Tree),学习使用Lambda创建表达式树,解析表达式树. 学习 ...

  2. [.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中)

    [.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中) 本节要点: 上节介绍了多线程的基本使用方法和基本应用示例,本节深入介绍.NET ...

  3. [.net 面向对象程序设计进阶] (15) 缓存(Cache)(二) 利用缓存提升程序性能

    [.net 面向对象程序设计进阶] (15) 缓存(Cache)(二) 利用缓存提升程序性能 本节导读: 上节说了缓存是以空间来换取时间的技术,介绍了客户端缓存和两种常用服务器缓布,本节主要介绍一种. ...

  4. JAVA进阶之旅(二)——认识Class类,反射的概念,Constructor,Field,Method,反射Main方法,数组的反射和实践

    JAVA进阶之旅(二)--认识Class类,反射的概念,Constructor,Field,Method,反射Main方法,数组的反射和实践 我们继续聊JAVA,这次比较有意思,那就是反射了 一.认识 ...

  5. 【C#进阶】委托那些事儿(一)

    一.简单的委托 1.1 委托的声明: C#当中,委托(delegate)是一种方法封装,也即委托对象可以作为一种传递方法的变量来使用. 委托也算是一种类,与类是平级的存在.在类中写delegate对象 ...

  6. 解密jQuery事件核心 - 委托设计(二)

    第一篇 http://www.cnblogs.com/aaronjs/p/3444874.html 从上章就能得出几个信息: 事件信息都存储在数据缓存中 对于没有特殊事件特有监听方法和普通事件都用ad ...

  7. ES5和ES6那些你必须知道的事儿(二)

    ES5和ES6那些你必须知道的事儿 ES5新增的东西 二.对象方法 1.Object.getPrototypeOf(object) 返回对象的原型 function Pasta(grain, widt ...

  8. Sass进阶之路,之二(进阶篇)

    Sass之二(进阶篇) 1. 数据类型 1.1 Number 数字类型,小数类型,带有像素单位的数字类型,全部都属于Number类型 Number类型详情请点击这里,下面是小例子 1.$n1: 1.2 ...

  9. C#进阶之路(二):事件

    一.初步了解事件 事件是委托的一个子集,为了满足“广播/订阅”模式的需求而生. 事件就是限制委托字段的包装器.限制外界对委托字段内部的访问.相当于封装. 事件就是能够发生的什么事情,主要有以下5个主体 ...

随机推荐

  1. UVa 230 Borrowers(map和set)

    I mean your borrowers of books - those mutilators of collections, spoilers of the symmetry of shelve ...

  2. python之生产者消费者模型

    #Auther Bob #--*--conding:utf-8 --*-- #生产者消费者模型,这里的例子是这样的,有一个厨师在做包子,有一个顾客在吃包子,有一个服务员在储存包子,这个服务员我们就可以 ...

  3. dede 复制文章,远程图片无法本地化

    解决方法: 1.找到dede的后台目录,在后台目录下的inc下找到inc_archives_functions.php 2.搜索GetCurContent函数,找到如下这段代码: preg_match ...

  4. struts框架问题四之获取到值栈的对象

    4. 问题四 : 如何获得值栈对象 * 获得值栈对象 有三种方法 * ValueStack vs1 = (ValueStack) ServletActionContext.getRequest().g ...

  5. Django开发问题及解决方法汇总

    1. manage.py@MxOnline > makemigrations users manage.py@MxOnline > migrate users 2. 操作django的ad ...

  6. 深入浅出 JMS(三) - ActiveMQ 安全机制

    深入浅出 JMS(三) - ActiveMQ 安全机制 一.认证 认证(Authentication):验证某个实体或者用户是否有权限访问受保护资源. MQ 提供两种插件用于权限认证: (一).Sim ...

  7. 深入浅出 JMS(四) - ActiveMQ 消息存储

    深入浅出 JMS(四) - ActiveMQ 消息存储 一.消息的存储方式 ActiveMQ 支持 JMS 规范中的持久化消息与非持久化消息 持久化消息通常用于不管是否消费者在线,它们都会保证消息会被 ...

  8. ejb 和pojo , jboss 和 tomcat

    EJB(企业JavaBeans)是普通JavaBeans的一种提升和规范,因为企业信息系统开发中需要一个可伸缩的性能和事务.安全机制,这样能保证企业系统平滑发展,而不是发展到一种规模重新更换一套软件系 ...

  9. CSS特效汇集

    http://www.lanrenzhijia.com/js/css3/ http://js.mobanwang.com/special/allcss/ 其他效果:http://www.cnblogs ...

  10. 共享内存system v(未编译)

    #include <stdio.h> #include <string.h> #include <errno.h> #include <unistd.h> ...