【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个主体 ...
随机推荐
- ubuntu下 openvpn客户端的配置
1.安装openvpn sudo apt-get install openvpn 2.配置openvpn 作为客户端,OpenVPN并没有特定的配置文件,而是由服务器提供方给出一个配置文件.对于认证, ...
- 5-Qt读取文件失败原因
刚开始准备读取当前目录下的txt文件: QFile file(":/xuhao.txt");或者: QFile file("./xuhao.txt"); 但是一 ...
- PHP资源列表(转)
一个PHP资源列表,内容包括:库.框架.模板.安全.代码分析.日志.第三方库.配置工具.Web 工具.书籍.电子书.经典博文等等. 初始翻译信息来自:<推荐!国外程序员整理的 PHP 资源大全& ...
- springmvc中@RequestMapping的使用
通过RequestMapping注解可以定义不同的处理器映射规则. 1.1 URL路径映射 @RequestMapping(value="/item")或@RequestMappi ...
- MacOs执行SQL出错(mysql)
上次修改过root密码之后,刚启动,执行sql就报错了. 错误是: Reset MySQL root password using ALTER USER statement after install ...
- HTML5新协议介绍 WebSocket
WebSocket protocol 是HTML5一种新的协议(protocol).它是实现了浏览器与服务器全双工通信(full-duplex). 现在,很多网站为了实现即时通讯(real-time) ...
- PHP-GTK的demo在windows下运行出现的问题
I am trying to use Firebird 2.5.2.26539 with wamp,When i enable the extensions of firebird in php: - ...
- Java的8种包装类:Wrapper Class
Java有8种基本数据类型,为什么又要出现对应的8种包装类: 1.Java的8种基本数据类型不支持面向对象编程机制 2.8种基本数据类型不具备“对象”的特性:没有成员变量.方法可供调用 3.例如:某个 ...
- SSH登录到远程linux机器并执行命令
一. 1.JSch是Java Secure Channel的缩写.JSch是一个SSH2的纯Java实现.它允许你连接到一个SSH服务器,并且可以使用端口转发,X11转发,文件传输等,当然你也可以集成 ...
- Ubuntu下部分软件的简介及安装
1.安装linux摄像头应用软件cheese sudo apt-get install cheese 2.Ubuntu Tweak Ubuntu Tweak是一款专门为Ubuntu(GNOME桌 ...