【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个主体 ...
随机推荐
- Find Peak Element(ARRAY - Devide-and-Conquer)
QUESTION A peak element is an element that is greater than its neighbors. Given an input array where ...
- Escape(状态压缩+最大流,好题)
Escape http://acm.hdu.edu.cn/showproblem.php?pid=3605 Time Limit: 4000/2000 MS (Java/Others) Memo ...
- ios 处理WKContentView的crash
http://www.jianshu.com/p/7ef5814a871b 解决WKContentView没有isSecureTextEntry方法造成的crash 程序中有web页面,使用W ...
- python数据类型内部结构解剖
一.前言 我们知道,python是一种动态语言,可以将任何类型的数据赋给任何变量,譬如: # Python代码 x = 4 x = "four" 这里已经将 x 变量的内容由整型转 ...
- php多进程 防止出现僵尸进程
对于用PHP进行多进程并发编程,不可避免要遇到僵尸进程的问题. 僵尸进程是指的父进程已经退出,而该进程dead之后没有进程接受,就成为僵尸进程(zombie)进程.任何进程在退出前(使用exit退出) ...
- IIS6.0创建新网站后,浏览显示需输入用户名和密码
1.首先我们需要创建一个用于匿名访问的账号. 我的电脑右键,电脑管理->本地用户和组->用户->新用户 注意勾选(用户不能更改密码和密码永不过期这两项) 2.右键新创建的用户-& ...
- IIS PHP Warning: Unknown: open(c:\\php\\tmp\\sess_xxx, O_RDWR) failed: Permission denied (13) in Unknown on line 0
出现这个问题的原因是你修改了php保存session的路径,但没有给用户访问该目录的权限. 右键该目录,给users用户组读.写的权限.
- EXP-00056:遇到oracle错误12154
执行命令如下: 引用 exp user/pwd@dbname file=d:text.dmp owner=(user) 碰到了错误: 引用 EXP-00056:遇到oracle错误12154 ORA- ...
- program by the way......
ostrich birds fruit apple constructor height weight method overload override base sub inherit extend ...
- PAT 1082 射击比赛(20)(代码+思路)
1082 射击比赛(20 分) 本题目给出的射击比赛的规则非常简单,谁打的弹洞距离靶心最近,谁就是冠军:谁差得最远,谁就是菜鸟.本题给出一系列弹洞的平面坐标(x,y),请你编写程序找出冠军和菜鸟.我们 ...