一、委托 delegate
1.在.Net平台下,委托类型用来定义和响应应用程序中的回调。事实上,.Net委托类型是一个类型安全的对象,指向可以以后调用的其他方法,.Net委托是内置支持
多路广播和异步方法调用的对象。.Net委托是类型安全的,如果将一个不“匹配模式”的方法传入委托,将会收到编译器错误。
2.委托类型包含3个重要的信息:
(1)它所调用的方法的名称;
(2)该方法的参数(可选);
(3)该方法的返回值(可选)。
.Net委托既可指向静态方法,也可以指向实例方法。
3.定义委托类型:public delegate int BinaryOp(int x, int y);
经过反编译:委托类型BinaryOp自动产生一个派生自System.MulticastDelegate(这是一个抽象类)的密封类,并生产3个方法:
(1)public virtual int Invoke(int x, int y);它被用来以同步方式调用委托对象维护的每个方法。
(2)public virtual IAsyncResult BeginInvoke(int x, int y, AsyncCallback callback, object @object);以异步方式调用委托对象维护的方法。
(3)public virtual int EndInvoke(IAsyncResult result);
4.委托还可以指向包含任意数量out或ref参数(以及用params关键字标记的数组参数)的方法。
5.System.MulticastDelegate 和 System.Delegate
我们永远不会直接派生自这些基类,如果我们使用delegate关键字,就间接创建了一个类,这个类“是” MulticastDelegate。
所有委托类型都共有的核心成员:
Method:此属性方法MethodInfo对象,用以表示委托维护的静态方法的详细信息。
Target:如果方法调用是定义在对象级别的(而不是静态方法),Target返回表示委托维护的方法的对象。如果Targe返回值为null,调用的方法是一个静态方法。
Combine():此静态方法给委托维护的列表添加一个方法。在C#中,使用重载+=操作符作为简化符号调用此方法。
GetInvocationList():此方法返回一个System.Delegate类型的数组,其中数组中的每个元素都表示一个可调用的特定方法。
Remove(),RemoveAll():这些静态方法从调用列表中移除一个(或所有)方法,在C#中,Remove()方法可通过使用重载-=操作符来调用。
6.使用委托发送对象状态通知
(1)定义将通知发送给调用者的委托类型。
(2)声明类中每个委托类型的成员变量。
(3)在类上创建辅助函数使调用者能指定由委托成员变量保存的方法。(注册函数)
(4)在类内部的某个方法中调用委托的方法列表。
示例:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace ConsoleApplication6
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. DoSomething d = new DoSomething("打地基");
  14. d.RegisterWorkEngineHandler(WorkEvent);
  15.  
  16. for (int i = ; i <= ; i++)
  17. {
  18. d.Work(i);
  19. }
  20.  
  21. Console.ReadKey();
  22. }
  23.  
  24. static void WorkEvent(string msg)
  25. {
  26. Console.WriteLine(msg);
  27. }
  28. }
  29.  
  30. class DoSomething
  31. {
  32. public string WorkName { get; set; }
  33.  
  34. public DoSomething(string workname)
  35. {
  36. this.WorkName = workname;
  37. }
  38.  
  39. public void Work(int step)
  40. {
  41. this.handler(string.Format("{0}工作:正在做第{1}步事情...", this.WorkName, step));
  42. }
  43.  
  44. // 定义委托类型
  45. public delegate void WorkEngineHandler(string msg);
  46.  
  47. // 声明私有的委托类型变量
  48. private WorkEngineHandler handler;
  49.  
  50. // 注册委托对象
  51. public void RegisterWorkEngineHandler(WorkEngineHandler handler)
  52. {
  53. this.handler = handler;
  54. }
  55. }
  56.  
  57. }
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace ConsoleApplication6
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. DoSomething d = new DoSomething("打地基");
  14. d.RegisterWorkEngineHandler(WorkEvent);
  15.  
  16. for (int i = ; i <= ; i++)
  17. {
  18. d.Work(i);
  19. }
  20.  
  21. Console.ReadKey();
  22. }
  23.  
  24. static void WorkEvent(string msg)
  25. {
  26. Console.WriteLine(msg);
  27. }
  28. }
  29.  
  30. class DoSomething
  31. {
  32. public string WorkName { get; set; }
  33.  
  34. public DoSomething(string workname)
  35. {
  36. this.WorkName = workname;
  37. }
  38.  
  39. public void Work(int step)
  40. {
  41. this.handler(string.Format("{0}工作:正在做第{1}步事情...", this.WorkName, step));
  42. }
  43.  
  44. // 定义委托类型
  45. public delegate void WorkEngineHandler(string msg);
  46.  
  47. // 声明私有的委托类型变量
  48. private WorkEngineHandler handler;
  49.  
  50. // 注册委托对象
  51. public void RegisterWorkEngineHandler(WorkEngineHandler handler)
  52. {
  53. this.handler = handler;
  54. }
  55. }
  56.  
  57. }

7.方法组转换语法:该特性允许我们在调用以委托作为参数的方法时直接提供方法的名称,而不是创建委托对象。
8.委托协变:因为委托是安全类型,它们不遵守继承的基本规则。协变允许我们构建一个委托,能指向返回类及相关继承体系的方法。
逆变:允许我们创建一个委托,指向多个方法,方法的参数是存在传统继承关系的对象。
9.泛型委托:通过类型参数来构建
public delegate void MyGenericDelegate<T>(T arg);
在不使用泛型的情况下模拟泛型委托:public delegate void MyDelegate(object arg);尽管这样可以把任何类型的数据发送到委托目标,但是会因此
失去类型安全并且可能还会有装箱/拆箱损失

二、事件 event
从头使用委托会有一些重复代码:定义委托,声明必要的成员变量以及创建自定义的注册/注销方法来保存封装等。
1.为了简化自定义方法的构建来为委托调用列表增加和删除方法,C#提供了event关键字。在编译器处理event关键字的时候,它会自动提供注册和注销方法以及委托类型
任何必要的成员变量。这些委托成员变量总是声明为私有的,因此不能直接从触发事件的对象访问它们。
2.定义一个事件分为两个步骤:首先,我们需要定义一个委托类型,它包含在事件触发时将要调用的方法。其次,通过C# evnet关键字用相关委托声明这个事件。
3.C#事件事实上会扩展为两个隐藏的公共方法,一个带add_前缀,另一个带remove_前缀,前缀后面是C#事件的名称。
4..Net基础类库底层委托的第一个参数是一个System.Object,第二个参数是派生自System.EventArgs的子类型。System.Object参数表示一个对发送事件的对象的引用,
第二个参数则表示与该事件相关的信息。
5.泛型EventHandler<T>委托
由于很多自定义委托接受object作为第一个参数,EventArgs派生类型作为第二个参数,我们可以通过使用泛型EventHandler<T>类型来进一步简化
public event EventHandler<MyEventArgs> Exploded;
6.按钮的单击事件

  1. // 摘要:
  2. // 表示将处理不包含事件数据的事件的方法。
  3. //
  4. // 参数:
  5. // sender:
  6. // 事件源。
  7. //
  8. // e:
  9. // 不包含任何事件数据的 System.EventArgs。
  10. [Serializable]
  11. [ComVisible(true)]
  12. public delegate void EventHandler(object sender, EventArgs e);
  13.  
  14. //
  15. // 摘要:
  16. // 在单击控件时发生。
  17. public event EventHandler Click;
  18.  
  19. this.button1.Click += new System.EventHandler(this.button1_Click);
  20. private void button1_Click(object sender, EventArgs e)
  21. {
  22.  
  23. }

三、Lambda表达式
1.手工定义一个由委托对象调用的方法显得有点繁琐,现在可以在事件注册时直接将一个委托与一段代码相关联,这种代码的正式名称称为匿名方法。
t.SomeEvent += delegate(参数){};
2.匿名方法不能访问定义方法中的ref或out参数;匿名方法中的本地变量不能与外部方法中的本地变量重名;匿名方法可以访问外部类作用域中的实例变量(或静态变量)。
3.Lambda表达式只是用更简单的方法来写匿名方法,彻底简化了对.Net委托类型的使用。
4.Lambda表达式规则:首先定义一个参数列表(0个或多个),“=>”标记紧随其后,然后就是处理这些参数的语句。

委托、事件和Lambda的更多相关文章

  1. 9、委托、事件、Lambda

    开始 关于委托,肯定是要有问题的. 第一个问题,委托用来干什么? 看.net中的表述:在.net平台下,委托类型用来定义和相应应用程序中的回调.(回调?处理内存中两个实体双向通信的一种技术.)   第 ...

  2. 委托,事件,lambda表达式

    开篇说明三个点: 委托是一种类型 事件是委托的实例 lambda表达式是一个方法(匿名方法) [未完待续]

  3. C# ~ 从 委托事件 到 观察者模式 - Observer

    委托和事件的部分基础知识可参见 C#/.NET 基础学习 之 [委托-事件] 部分: 参考 [1]. 初识事件 到 自定义事件: [2]. 从类型不安全的委托 到 类型安全的事件: [3]. 函数指针 ...

  4. Unity C#笔记 委托&事件

    C#的委托与事件搭配,即是观察者模式的一种实现. 因为观察者模式的原理很易懂,不作多讲,本文纯粹用于记录语法. delegate(委托) //声明没有参数,没有返回值的委托类型XXXX public ...

  5. Delegate,Action,Func,匿名方法,匿名委托,事件 (转载)

    Delegate,Action,Func,匿名方法,匿名委托,事件 (转载) 一.委托Delegate 一般的方法(Method)中,我们的参数总是string,int,DateTime...这些基本 ...

  6. C#委托,事件理解入门 (译稿)

    原文地址:http://www.codeproject.com/Articles/4773/Events-and-Delegates-Simplified 引用翻译地址:http://www.cnbl ...

  7. 关于ios使用jquery的on,委托事件失效

    $('.parents').on("click",'.child',function(){}); 类似上面这种,在ios上点击"child"元素不会起作用,解决 ...

  8. Observer设计模式中-委托事件-应用在消息在窗体上显示

    Observer设计模式:监视者模式.在类中的方法中处理的结果或者消息通过事件委托 的方式发送给主窗体. 因为在其它类中直接访问主窗体类,显示内容是不能直接调用控件赋值的,当然也有别的类似查阅控件名, ...

  9. Asp.net用户控件和委托事件

    在Asp.net系统制作过程中,门户类型的网站,我们可以用DIV+CSS+JS+Ajax全部搞定,但是一旦遇到界面元素比较复杂的时候,还是UserControl比较方便一些,各种封装,各种处理,然后拖 ...

  10. jQuery里面的普通绑定事件和on委托事件

    以click事件为例: 普通绑定事件:$('.btn1').click(function(){}绑定 on绑定事件:$(document).on('click','.btn2',function(){ ...

随机推荐

  1. 常见的HTTP错误总结

    一般来说HTTP2XX,代表请求正常完成,HTTP3XX代表网站重定向,HTTP4XX,代表客户端出现错误,HTTP5XX,代服务器端出现了错误 HTTP301:请求的数据具有新的位置 HTTP302 ...

  2. 第六章Linux的文件权限与目录配置

    一.Linux用户分类 1.Linux用户分为:(文件|目录)所有者(OWN),(同组内的)用户组,其他人; 2.一个天神:root;,几乎能完成任何事.... 二.目录权限的意义 目录的权限和文件的 ...

  3. Linux 两个目录浅对比拷贝

    对比两个目录内容,然后拷贝! #!/usr/bin/python# -*-coding:utf-8 -*-import osimport sysimport shutildef get_dir_con ...

  4. jruby中的异常

    先看看ruby中的异常知识: 异常处理raise 例子: raise raise "you lose" raise SyntaxError.new("invalid sy ...

  5. SequoiaDB版本升级及导入导出工具说明

    升级SequoiaDB数据库指导 SequoiaDB安装路径:SDB_HOME=/opt/sequoiadb 数据存储路径:DATABASE=/ opt/sequoiadb/database 一.导出 ...

  6. hdu 5443 The Water Problem

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5443 The Water Problem Description In Land waterless, ...

  7. Windows Phone中Wallet钱包的使用

    前言 Windows Phone 8中加入了钱包Wallet这个功能,这个功能非常的有意思,开发者可以通过Wallet提供的API创建获取Wallet中的商品.统一管理用户的收集优惠券.信用卡.成员资 ...

  8. 教你怎么安装RabbitMQ

    以下命令以root用户运行:#echo 'deb http://www.rabbitmq.com/debian/ testing main' >> /etc/apt/sources.lis ...

  9. 【坑】执行Consumer的时候发生java.net.UnknownHostException错误

    [时间]: 2016/4/8 17:30 [问题]: kafka执行Consumer实例的时候,发生了一下错误. kafka配置文件server.properties如下: zookeeper配置文件 ...

  10. win7虚拟打印驱动开发注意事项

    win7虚拟打印驱动开发注意事项 通过控制面板安装遇到以下问题:错误1.提示“Printer driver was not installed. Operation could not be comp ...