【C#进阶】委托那些事儿(二)
二、传统的委托
接下来讲一讲方法参数。下面以“餐馆服务员为客户下单”[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#进阶】委托那些事儿(二)的更多相关文章
- [.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门
[.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门 本节导读: 认识表达式树(Expression Tree),学习使用Lambda创建表达式树,解析表达式树. 学习 ...
- [.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中)
[.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中) 本节要点: 上节介绍了多线程的基本使用方法和基本应用示例,本节深入介绍.NET ...
- [.net 面向对象程序设计进阶] (15) 缓存(Cache)(二) 利用缓存提升程序性能
[.net 面向对象程序设计进阶] (15) 缓存(Cache)(二) 利用缓存提升程序性能 本节导读: 上节说了缓存是以空间来换取时间的技术,介绍了客户端缓存和两种常用服务器缓布,本节主要介绍一种. ...
- JAVA进阶之旅(二)——认识Class类,反射的概念,Constructor,Field,Method,反射Main方法,数组的反射和实践
JAVA进阶之旅(二)--认识Class类,反射的概念,Constructor,Field,Method,反射Main方法,数组的反射和实践 我们继续聊JAVA,这次比较有意思,那就是反射了 一.认识 ...
- 【C#进阶】委托那些事儿(一)
一.简单的委托 1.1 委托的声明: C#当中,委托(delegate)是一种方法封装,也即委托对象可以作为一种传递方法的变量来使用. 委托也算是一种类,与类是平级的存在.在类中写delegate对象 ...
- 解密jQuery事件核心 - 委托设计(二)
第一篇 http://www.cnblogs.com/aaronjs/p/3444874.html 从上章就能得出几个信息: 事件信息都存储在数据缓存中 对于没有特殊事件特有监听方法和普通事件都用ad ...
- ES5和ES6那些你必须知道的事儿(二)
ES5和ES6那些你必须知道的事儿 ES5新增的东西 二.对象方法 1.Object.getPrototypeOf(object) 返回对象的原型 function Pasta(grain, widt ...
- Sass进阶之路,之二(进阶篇)
Sass之二(进阶篇) 1. 数据类型 1.1 Number 数字类型,小数类型,带有像素单位的数字类型,全部都属于Number类型 Number类型详情请点击这里,下面是小例子 1.$n1: 1.2 ...
- C#进阶之路(二):事件
一.初步了解事件 事件是委托的一个子集,为了满足“广播/订阅”模式的需求而生. 事件就是限制委托字段的包装器.限制外界对委托字段内部的访问.相当于封装. 事件就是能够发生的什么事情,主要有以下5个主体 ...
随机推荐
- UVa 230 Borrowers(map和set)
I mean your borrowers of books - those mutilators of collections, spoilers of the symmetry of shelve ...
- python之生产者消费者模型
#Auther Bob #--*--conding:utf-8 --*-- #生产者消费者模型,这里的例子是这样的,有一个厨师在做包子,有一个顾客在吃包子,有一个服务员在储存包子,这个服务员我们就可以 ...
- dede 复制文章,远程图片无法本地化
解决方法: 1.找到dede的后台目录,在后台目录下的inc下找到inc_archives_functions.php 2.搜索GetCurContent函数,找到如下这段代码: preg_match ...
- struts框架问题四之获取到值栈的对象
4. 问题四 : 如何获得值栈对象 * 获得值栈对象 有三种方法 * ValueStack vs1 = (ValueStack) ServletActionContext.getRequest().g ...
- Django开发问题及解决方法汇总
1. manage.py@MxOnline > makemigrations users manage.py@MxOnline > migrate users 2. 操作django的ad ...
- 深入浅出 JMS(三) - ActiveMQ 安全机制
深入浅出 JMS(三) - ActiveMQ 安全机制 一.认证 认证(Authentication):验证某个实体或者用户是否有权限访问受保护资源. MQ 提供两种插件用于权限认证: (一).Sim ...
- 深入浅出 JMS(四) - ActiveMQ 消息存储
深入浅出 JMS(四) - ActiveMQ 消息存储 一.消息的存储方式 ActiveMQ 支持 JMS 规范中的持久化消息与非持久化消息 持久化消息通常用于不管是否消费者在线,它们都会保证消息会被 ...
- ejb 和pojo , jboss 和 tomcat
EJB(企业JavaBeans)是普通JavaBeans的一种提升和规范,因为企业信息系统开发中需要一个可伸缩的性能和事务.安全机制,这样能保证企业系统平滑发展,而不是发展到一种规模重新更换一套软件系 ...
- CSS特效汇集
http://www.lanrenzhijia.com/js/css3/ http://js.mobanwang.com/special/allcss/ 其他效果:http://www.cnblogs ...
- 共享内存system v(未编译)
#include <stdio.h> #include <string.h> #include <errno.h> #include <unistd.h> ...