前言: 

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());
  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. public abstract class Subject
  23. {
  24. public ObserverDelegate observerDelegate;
  25.  
  26. //增加观察者
  27. public void Attach(ObserverDelegate observer)
  28. {
  29. observerDelegate += observer;
  30. }
  31.  
  32. //移除观察者
  33. public void Remove(ObserverDelegate observer)
  34. {
  35. observerDelegate -= observer;
  36. }
  37.  
  38. //像观察者发通知
  39. public void Notify()
  40. {
  41. if (observerDelegate != null)
  42. {
  43. observerDelegate();
  44. }
  45. }
  46. }
  47.  
  48. //具体主题类
  49. public class ConcreteSubject : Subject
  50. {
  51. public string SubjectState { get; set; }
  52. }
  53.  
  54. //具体观察者
  55. public class ConcreteObserver
  56. {
  57. private string observerState;
  58. private string name;
  59. private ConcreteSubject subject;
  60.  
  61. public ConcreteObserver(ConcreteSubject subject, string name)
  62. {
  63. this.subject = subject;
  64. this.name = name;
  65. }
  66.  
  67. //实现抽象观察者中的更新操作
  68. public void Update()
  69. {
  70. observerState = subject.SubjectState;
  71. Console.WriteLine("The observer's state of {0} is {1}", name, observerState);
  72. }
  73. }
  74. }

二,事件 event

(1) 事件时委托的封装,可以理解为一种特殊的委托。
(2) 事件里面其实就两个方法(即add_event() 和 remove_event())和一个私有的委托变量,这两个方法里面分别是对这个私有的委托变量进

行的合并和移除,当调用事件的+=时其实是调用的事件里的add_event()方法,同样-=调用的是remove_event()方法
(3) 事件只能够从对象外部增加新的响应方法和删除已知的响应方法,而不能主动去触发事件和获取其他注册的响应方法等信息。如果使用

公有的delegate则不能做这些限制,也就是说事件对委托做了限制,使委托使用起来更加方便。
也有人说事件是对委托的阉割,大概也是这个意思。

这里事件没有做过多的阐述, 看到一个关于事件讲解的比较不错的博文, 推荐大家看下吧: http://www.cnblogs.com/landeanfen/p/4721525.html

PS: 本博客只是为了记录自己学习中的收获, 俗话说 好记性不如烂笔头. 望自己能够坚持下去.

[读书笔记]C#学习笔记二: 委托和事件的用法及不同.的更多相关文章

  1. [读书笔记]C#学习笔记一: .Net Framwork

    前言: 一次偶然的机会  在园子里看到@Learning hard 出版的一本书: <<C#学习笔记>>, 然后买来 一直到现在读完, 感觉很不错, 适合入门, 书中内容是从C ...

  2. [读书笔记]C#学习笔记三: C#类型详解..

    前言 这次分享的主要内容有五个, 分别是值类型和引用类型, 装箱与拆箱,常量与变量,运算符重载,static字段和static构造函数. 后期的分享会针对于C#2.0 3.0 4.0 等新特性进行. ...

  3. [读书笔记]C#学习笔记八:StringBuilder与String详解及参数传递问题剖析

    前言 上次在公司开会时有同事分享windebug的知识, 拿的是string字符串Concat拼接 然后用while(true){}死循环的Demo来讲解.其中有提及string操作大量字符串效率低下 ...

  4. [读书笔记]C#学习笔记四: C#2.0泛型 可控类型 匿名方法和迭代器

    前言 C#1.0的委托特性使方法作为其他方法的参数来传递,而C#2.0 中提出的泛型特性则使类型可以被参数化,从而不必再为不同的类型提供特殊版本的实现方法.另外C#2.0还提出了可空类型,匿名方法和迭 ...

  5. C#学习笔记(四):委托和事件

    刚开始学习C#的时候就写过了,直接给地址了: 委托.匿名函数.Lambda表达式和事件的学习 委托学习续:Action.Func和Predicate

  6. 《Inside C#》笔记(十二) 委托与事件

    C#的委托与C++的函数指针类似,但委托是类型安全的,意味着指针始终会指向有效的函数.委托的使用主要有两种:回调和事件. 一 将委托作为回调函数 在需要给一个函数传递一个函数指针,随后通过函数指针调用 ...

  7. [读书笔记]C#学习笔记七: C#4.0中微小改动-可选参数,泛型的可变性

    前言 下面就开始总结C#4.0的一些变化了, 也是这本书中最后的一点内容了, 这一部分终于要更新完了. 同时感觉再来读第二遍也有不一样的收获. 今天很嗨的是武汉下雪了,明天周六,一切都是这么美好.哈哈 ...

  8. [读书笔记]C#学习笔记六: C#3.0Lambda表达式及Linq解析

    前言 最早使用到Lambda表达式是因为一个需求:如果一个数组是:int[] s = new int[]{1,3,5,9,14,16,22};例如只想要这个数组中小于15的元素然后重新组装成一个数组或 ...

  9. C#学习笔记(十七):委托、事件、观察者模式、匿名委托和lambert表达式

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

随机推荐

  1. iOS 发送Email

    第一步:在程序中添加MessageUi.framework框架 第二步:引入#import <MessageUI/MessageUI.h>头文件 第三步:代码实现 3.1判断是否可以发送邮 ...

  2. Linux编程获取本地IP

    #include <stdio.h> #include <sys/types.h> #include <ifaddrs.h> #include <netine ...

  3. android笔记:DatePickerDialog日期设置对话框

    在开发中,可以通过DatePickerDialog来设置日期,TimePickerDialog来设置时间. 实例化DatePickerDialog对象之后,再调用show方法就可以显示对话框了. 具体 ...

  4. ContentProvider 增删改查通讯录

    一.通讯录应用介绍 通讯录应用是Android自带的应用程序,我们看到此应用的时候,可能只认为这是一个应用,用数据库存储数据,但是实际上不是这样的. 通讯录是ContentProvider的应用,通讯 ...

  5. Python:装饰器

    格式:在执行的参数前加上@functon 例1:传一个参数 #模拟验证功能 def login(auth): def fun(arg): #为了避免程序一执行的时候就执行验证,需要再加一层函数. pr ...

  6. chm手册显示已取消到该网页的导航

    解决:在chm右键查看有没有解除锁定选项.1.右键单击chm文件,选择属性:2.在最下面点击“解除锁定”并确定后,再次打开chm,就正常了

  7. uglifyjs压缩JS的

    一.故事总有其背景 年末将至,很多闲适的时间,于是刷刷微博,接触各种纷杂的信息——美其名曰“学习”.运气不错,遇到了一个新名词,uglifyjs. 据说是用来压缩JS文件的,据说还能优化JS,据说是基 ...

  8. ActiveX控件dsoFramer的使用(word、excel、PPT)

    dsoframer是微软提供一款开源的用于在线编辑.调用Word. Excel .PowerPoint等的ActiveX控件.国内很多著名的OA中间件,电子印章,签名留痕等大多数是依此改进而来的. 一 ...

  9. [Shell]字符截取命令:cut, printf, awk, sed

    ------------------------------------------------------------------------------------------- [cut命令] ...

  10. web.xml相关知识摘录整理

    web.xml 中的listener. filter.servlet 加载顺序及其详解 在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人 ...