[读书笔记]C#学习笔记二: 委托和事件的用法及不同.
前言:
C#委托是什么
c#中的委托可以理解为函数的一个包装, 它使得C#中的函数可以作为参数来被传递, 这在作用上相当于C++中的函数指针. C++用函数指针获取函数的入口地址, 然后通过这个指针来实现对函数的操作.
委托的定义和方法的定义类似, 只是在定义的前面多了一个delegate关键字.
正文:
委托可以被视为一个更高级的指针,它不仅仅能把地址传指向另一个函数,而且还能传递参数,返回值等多个信息。
系统还为委托对象自动生成了同步,异步的调用方式,开发人员使用BeginInvoke,EndInvoke方法就可以抛开Thread而直接使用多线程调用。
一, 委托
用IL 分析可看出Delegate继承自System.MulticastDelegate类,并自动生成BeginInvoke,EndInvoke,Invoke三种常见的方法。
Invoke方法是用于同步调用委托对象的对应方法,而BeginInvoke,EndInvoke是用于以异步方式调用对应方法的。
1.1 简单的委托
当建立委托对象时,委托的参数类型必须与委托方法相对应。只要向建立委托对象的构造函数中输入方法名称example.Method,委托就会直
接绑定此方法。
使用myDelegate.Invoke(string message),就能显式调用委托方法。
但在实际的操作中,我们无须用到 Invoke 方法,而只要直接使用myDelegate(string message),就能调用委托方法。
1 class Program 2 { 3 void MyDelegate(string message); 4 5 public class Example 6 { 7 public void Method(string message) 8 { 9 MessageBox.Show(message); 10 } 11 } 12 13 static void Main(string[] args) 14 { 15 Example example=new Example(); 16 MyDelegate myDelegate=new MyDelegate(example.Method); 17 myDelegate("Hello World"); 18 Console.ReadKey(); 19 } 20 }
1.2 带返回值的委托
当建立委托对象时,委托的返回值必须与委托方法相对应。使用下面的例子,方法将返回 “Hello Leslie” 。
1 class Program 2 { 3 delegate string MyDelegate(string message); 4 5 public class Example 6 { 7 public string Method(string name) 8 { 9 return "Hello " + name; 10 } 11 } 12 13 static void Main(string[] args) 14 { 15 Example example=new Example(); 16 //绑定委托方法 17 MyDelegate myDelegate=new MyDelegate(example.Method); 18 //调用委托,获取返回值 19 string message = myDelegate("Leslie"); 20 Console.WriteLine(message); 21 Console.ReadKey(); 22 } 23 }
1.3 多路广播委托
在上面提过,委托类继承于MulticastDelegate,这使委托对象支持多路广播,即委托对象可以绑定多个方法。
当输入参数后,每个方法会按顺序进行迭代处理,并返回最后一个方法的计算结果。
下面的例子中,Price 类中有两个计算方法,Ordinary 按普通的9.5折计算,Favourable 按优惠价 8.5 折计算。
委托同时绑定了这两个方法,在输入参数100以后,Ordinary、Favourable这两个方法将按顺序迭代执行下去,最后返回 Favourable 方法的
计算结果 85。
1 delegate double MyDelegate(double message); 2 public class Price 3 { 4 public double Ordinary(double price) 5 { 6 double price1 = 0.95 * price; 7 Console.WriteLine("Ordinary Price : "+price1); 8 return price1; 9 } 10 11 public double Favourable(double price) 12 { 13 double price1 = 0.85 * price; 14 Console.WriteLine("Favourable Price : " + price1); 15 return price1; 16 } 17 18 static void Main(string[] args) 19 { 20 Price price = new Price(); 21 //绑定Ordinary方法 22 MyDelegate myDelegate = new MyDelegate(price.Ordinary); 23 //绑定Favourable方法 24 myDelegate += new MyDelegate(price.Favourable); 25 //调用委托 26 Console.WriteLine("Current Price : " + myDelegate(100)); 27 Console.ReadKey(); 28 } 29 }
1.4 Observer模式中的事件与委托
1 class Program 2 { 3 public delegate void ObserverDelegate(); 4 5 static void Main(string[] args) 6 { 7 // 具体主题角色通常用具体自来来实现 8 ConcreteSubject subject = new ConcreteSubject(); 9 10 //传入的只是观察者的通过方法。 11 subject.Attach(new ConcreteObserver(subject, "Observer A").Update); 12 subject.Attach(new ConcreteObserver(subject, "Observer B").Update); 13 subject.Attach(new ConcreteObserver(subject, "Observer C").Update); 14 15 subject.SubjectState = "Ready"; 16 subject.Notify(); 17 18 Console.Read(); 19 } 20 21 22 //抽象主体类 23 public abstract class Subject 24 { 25 public ObserverDelegate observerDelegate; 26 27 //增加观察者 28 public void Attach(ObserverDelegate observer) 29 { 30 observerDelegate += observer; 31 } 32 33 //移除观察者 34 public void Remove(ObserverDelegate observer) 35 { 36 observerDelegate -= observer; 37 } 38 39 //像观察者发通知 40 public void Notify() 41 { 42 if (observerDelegate != null) 43 { 44 observerDelegate(); 45 } 46 } 47 } 48 49 //具体主题类 50 public class ConcreteSubject : Subject 51 { 52 public string SubjectState { get; set; } 53 } 54 55 //具体观察者 56 public class ConcreteObserver 57 { 58 private string observerState; 59 private string name; 60 private ConcreteSubject subject; 61 62 public ConcreteObserver(ConcreteSubject subject, string name) 63 { 64 this.subject = subject; 65 this.name = name; 66 } 67 68 //实现抽象观察者中的更新操作 69 public void Update() 70 { 71 observerState = subject.SubjectState; 72 Console.WriteLine("The observer's state of {0} is {1}", name, observerState); 73 } 74 } 75 }
二,事件 event
(1) 事件时委托的封装,可以理解为一种特殊的委托。
(2) 事件里面其实就两个方法(即add_event() 和 remove_event())和一个私有的委托变量,这两个方法里面分别是对这个私有的委托变量进
行的合并和移除,当调用事件的+=时其实是调用的事件里的add_event()方法,同样-=调用的是remove_event()方法
(3) 事件只能够从对象外部增加新的响应方法和删除已知的响应方法,而不能主动去触发事件和获取其他注册的响应方法等信息。如果使用
公有的delegate则不能做这些限制,也就是说事件对委托做了限制,使委托使用起来更加方便。
也有人说事件是对委托的阉割,大概也是这个意思。
这里事件没有做过多的阐述, 看到一个关于事件讲解的比较不错的博文, 推荐大家看下吧: http://www.cnblogs.com/landeanfen/p/4721525.html
PS: 本博客只是为了记录自己学习中的收获, 俗话说 好记性不如烂笔头. 望自己能够坚持下去.
[读书笔记]C#学习笔记二: 委托和事件的用法及不同.相关推荐
- 《算法笔记》学习笔记(1)
<算法笔记>学习笔记(1) 2021/4/7号 晚上21:36开始学习 第二章 c++/c快速入门 有的时候不要在一个程序中同时使用cout 和 printf 有的时候会出现问题. 头文件 ...
- TED阅读笔记,学习笔记
TED阅读笔记,学习笔记,大约200集 每日一读,一起来学英语吧 自用,喜欢的帮忙点个赞
- [读书笔记]C#学习笔记三: C#类型详解..
前言 这次分享的主要内容有五个, 分别是值类型和引用类型, 装箱与拆箱,常量与变量,运算符重载,static字段和static构造函数. 后期的分享会针对于C#2.0 3.0 4.0 等新特性进行. ...
- c语言for循环笔记,【学习笔记】【C语言】循环结构-for
1.使用: for (语句1; 条件; 语句2) { 循环体 } 语句1:初始化语句 语句2:增量语句(执行完循环体后再执行的语句) 1.for一开始就会执行一次语句1(整个for循环只会执行一次) ...
- 学习笔记 mysql_MySQL 学习笔记
MySQL 学习笔记 1 定义 数据库中的表:一行叫一条记录.每一列叫一个属性,或一个字段. 主键:表中的某个特殊字段,具有唯一的确定的值,可以根据该字段唯一的确定一条记录 外键:表中的某个字段的值为 ...
- php基础教学笔记,php学习笔记:基础知识
php学习笔记:基础知识 2.每行结尾不允许有多余的空格 3.确保文件的命名和调用大小写一致,是由于类Unix系统上面,对大小写是敏感的 4.方法名只允许由字母组成,下划线是不允许的,首字母要小写,其 ...
- 伤寒论(太阳病笔记)——学习笔记,更待前辈指点
学而不止,更新不止.本为自我学习笔记,更待前辈指点 太阳病 1. 成因: ① 风寒邪气侵袭体表.②少阴病阳气恢复,脏邪还腑,阴病出阳(阴病出阳) 病位 足太阳膀胱经,足太阳膀胱腑,手太阴肺 足太阳旁观 ...
- python3笔记_Python3学习笔记(四)
原标题:Python3学习笔记(四) 错误.调试和测试 程序运行中,可能会遇到BUG.用户输入异常数据以及其它环境的异常,这些都需要程序猿进行处理.Python提供了一套内置的异常处理机制,供程序猿使 ...
- oracle goldengate学习笔记,【学习笔记】Oracle goldengate monitor使用笔记
天萃荷净 Oracle研究中心学习笔记:分享一篇关于Oracle数据库goldengate monitor的使用笔记. 本站文章除注明转载外,均为本站原创: 转载自love wife & lo ...
最新文章
- echarts图形报表缓存问题(option数据缓存)
- Chapter1 CLR的执行模式
- DevOps的前世今生
- 手把手教你用7行代码实现微信聊天机器人 -- Python wxpy
- 响应式方案调研及前端开发管理思考
- mysql mgr 配置_MySQL5.7 MGR安装配置
- 任务七:实现常见的技术产品官网的页面架构及样式布局
- Thrift框架使用C++的一个demo
- Linux 查看ssh登录日志 ssh登录记录
- 深夜,基友给我发了个某短视频app,我没忍住把它给...
- php 7.4 编译安装
- Aircrack-ng破解无线WIFI密码
- 基于Android 的手机传感器检测
- 网站漏洞修复之metinfo SQL注入漏洞
- u盘插在linux显示不了,U盘在Linux下显示不正常的解决方法
- VMBox CentOS安装记录
- 【哈利波特全集】哈利波特1-7
- 给文档添加签名,介绍用iPhone的实例,安卓手机类似
- 安卓Timer+TimeTask实现定时器任务
- 您的浏览器暂不支持计算机上传文件的大小,电脑中谷歌浏览器无法上传图片的解决方法...