c 委托使用方法1

上传人:aa****6 文档编号:38181330 上传时间:2018-04-28 格式:PDF 页数:41 大小:999.08KB
返回 下载 相关 举报
c  委托使用方法1_第1页
第1页 / 共41页
c  委托使用方法1_第2页
第2页 / 共41页
c  委托使用方法1_第3页
第3页 / 共41页
c  委托使用方法1_第4页
第4页 / 共41页
c  委托使用方法1_第5页
第5页 / 共41页
点击查看更多>>
资源描述

《c 委托使用方法1》由会员分享,可在线阅读,更多相关《c 委托使用方法1(41页珍藏版)》请在金锄头文库上搜索。

1、在 C#中,委托(delegate)是一种引用类型,在其他语言中,与委托最接近的是 函数指针,但委托不仅存储对方法入口点的引用,还存储对用于调用方法的对象 实例的引用。 简单的讲委托(delegate)是一种类型安全的函数指针,首先,看下面的示例程 序,在 C+中使用函数指针。 首先,存在两个方法:分别用于求两个数的最大值和最小值。 int Max(int x,int y) return xy?x:y; int Min(int x,int y) return x 上面两个函数的特点是:函数的返回值类型及参数列表都一样。那么,我们可以 使用函数指针来指代这两个函数,并且可以将具体的指代过程交给用

2、户,这样, 可以减少用户判断的次数。 下面我们可以建立一个函数指针,将指向任意一个方法,代码如下所示:/定义一个函数指针定义一个函数指针,并声明该指针可以指向的函数的返回值为并声明该指针可以指向的函数的返回值为 int 类型类型,参参数列表中包数列表中包/括两个括两个 int 类型的参数类型的参数int (*p)(int,int);/让指针让指针 p 指向指向 Max 函数函数p=max;/利用指针调用利用指针调用 Maxc=(*p)(5,6); 我们的问题在于,上面的代码中,为什么不直接使用 Max 函数,而是利用一个 指针指向 Max 之后,再利用指针调用 Max 函数呢? 实际上,使用指

3、针的方便之处就在于,当前时刻可以让指针 p 指向 Max,在后面 的代码中,我们还可以利用指针 p 再指向 Min 函数,但是不论 p 指向的是谁, 调用 p 时的形式都一样,这样可以很大程度上减少判断语句的使用,使代码的可 读性增强! 在 C#中,我们可以使用委托(delegate)来实现函数指针的功能,也就是说,我 们可以像使用函数指针一样, 在运行时利用 delegate 动态指向具备相同签名的方 法(所谓的方法签名,是指一个方法的返回值类型及其参数列表的类型)。6.1 使用委托(使用委托(delegate)6.1.1 委托的建立委托的建立 建立委托(delegate),过程有点类似于建

4、立一个函数指针。过程如下: 1. 建立一个委托类型,并声明该委托可以指向的方法的签名(函数原型)delegate void MyDelegate(int a,int b); 2.建立一个委托类的实例,并指向要调用的方法/利用委托类的构造方法指定,这是最为常见的一种方式利用委托类的构造方法指定,这是最为常见的一种方式MyDelegate md=new MyDelegate(Max);/利用自动推断方式来指明要调用的方法,该形式更类型于函数指针利用自动推断方式来指明要调用的方法,该形式更类型于函数指针MyDelegate md=Max; 3.利用委托类实例调用所指向的方法 int c=md(4,5

5、); 下面通过实例来演示 C#中委托的使用。 案例操作案例操作 020601020601:利用委托实现利用委托实现 方法的动态调用方法的动态调用 首先,添加如下控件: 两个 RadioButton,分别用来让用户 选择求最大值以及求最小值 二个 TextBox,用来输入两个操作数 一个 TextBox,用来显示运算结果 一个 Button,用来执行运算 界面如下图所示:下一步,在窗口中添加两个方法:Max,Min,这两方法的代码如下: int Max(int x,int y) return xy?x:y; int Min(int x,int y) return x 窗口中的代码,如下图所示:下

6、一步: 为了使用委托来实现动态指向, 我们需要建立一个委托类“MyDelegate”, 并建立该委托类型的一个实例,如下图所示:上面的代码中,我们可以发现,此时,还没有让 MyDelegate 类型的实例“md”指 向任何一个方法(即:md 的值为 null),原因是:在编写代码的时候,我们还 不知道用户想要调用哪一个方法。 下一步, 分别为两个 RadioButton 编写它们的“CheckedChanged”事件, 代码如下: private void rbtMax_CheckedChanged(object sender, EventArgs e) if (this.rbtMax .Ch

7、ecked =true) this.md = new MyDelegate(this.Max ); private void rbtMin_CheckedChanged(object sender, EventArgs e) if (this.rbtMin .Checked =true) this.md = new MyDelegate(this.Min ); 这段代码是,如果用户选择了求最大值的 RadioButton,则让 MyDelegate 类型的 实例“md”指向 Max 方法,如果用户选择了求最小值的 RadioButton,则让 MyDelegate 类型的实例“md”指向 Mi

8、n 方法。这样作的目的,就是要把选择的过 程交给用户。 下一步,我们为界面中的 Button 编写 Click 事件,并利用委托来调用求最值的方 法。代码如下所示: private void btGetResult_Click(object sender, EventArgs e) if (this.md =null ) MessageBox.Show(“委托委托 md 没有指向任何方法!没有指向任何方法!“);return; int a = int.Parse(this.tbxOP1 .Text ); int b = int.Parse(this.tbxOP2 .Text ); int c

9、= this.md(a,b); this.tbxResult.Text = c.ToString(); 从上面的代码中,可以发现,在使用委托之前,先要判断其值是否为空,如果不 为空,则可以进行调用,同时,使用者可以看到,在调用 md 时,我们并没有关 心 md 到底指向了哪一个方法,总之,md 不为空的时候,就一定会指向 Max 和 Min 当中的一个。 为了让求最大值的RadioButton在程序开始运行的时候就被选中, 在Form的Load 事件中添加如下代码: private void Form1_Load(object sender, EventArgs e) this.md = ne

10、w MyDelegate(this.Max ); 运行的效果如下图所示:求最大值求最小值 委托使用的注意事项委托使用的注意事项 在 C中,所有的委托都是从 System.MulticastDelegate 类派生的。 委托隐含具有 sealed 属性,即不能 用来派生新的类型。 委托最大的作用就是为类的事件绑 定事件处理程序。 在通过委托调用函数前,必须先检 查委托是否为空(null),若非空,才 能调用函数。 在委托实例中可以封装静态的方法 也可以封装实例方法。 在创建委托实例时,需要传递将要 映射的方法或其他委托实例以指明委托 将要封装的函数原型(.NET 中称为方法 签名:signatu

11、re)。注意,如果映射的 是静态方法,传递的参数应该是类名.方 法名,如果映射的是实例方法,传递的 参数应该是实例名.方法名。 只有当两个委托实例所映射的方法 以及该方法所属的对象都相同时,才认 为它们是想等的(从函数地址考虑)。6.1.2 讨论委托类型讨论委托类型 从上面的案例中,我们可以发现,在使用委托之前,先要定义一个委托类型,如 下所示: delegate int MyDelegate(int a, int b); MyDelegate md = null; 既然叫做委托类型,就说明 MyDelegate 实际上是一个类,上面的写法只是一种 简 单 的 缩 略 写 法 , 实 际 上

12、, 我 们 自 己 定 义 的 委 托 , 都 是 继 承 自 System.MulticastDelegate 类的,但是我们确不能自己定义一个类去继承自 System.MulticastDelegate 类,为了证明这点,我们可以使用 ildasm 工具,来查看 “MyDelegate”的 IL 代码。首先在 Visual Studio 控制台,如下图所示:在打开的“Visual Studio2008 Command Prompt”窗口中, 输入 ildam,如下图所示:运行之后,会出现 ildasm 的窗口,如下图所示:下一步,打开刚才编译好的 exe 程序,如下图所示:展开结点,并找到

13、“MyDelegate”类型,将其展开,如下图所示:在上图中,我们可以看到,对“MyDelegate”,存在如下“说明”: extends mscorlibSystem.MulticastDelegate 与此同时,还存在着四个方法,即: .ctor:构造方法 BeginInvoke EndInvoke Invoke MulticastDelegateMulticastDelegate 类类 MultiDelegate 类是一个特殊类(Special Class),和 System.Delegate 类一样,该 类只能够被编译器以及内置的工具类所继承, 我们自定义的类是不能够显式的继 承自该类

14、的。 MultiDelegate 类当中可以包括一个委托的链表, 这个表中, 可以包括一个或多个 元素(每个元素都是一个委托),我们可以将这个表称为调用链。当我们调用一 个 MultiDelegate 的时候, 位于该 MultiDelegate 调用链中的委托就会被串行调用。 这样我们就可以只调用一个方法,而多个相同签名的方法就会同时被串行调用。 关于多播委托的说明,我们会在后面的内容中进行讲解。 InvokeInvoke 方法方法为了解释 Invoke 方法,我们先来回顾一下,当一个委托指向了一个方法时是如 何调用的,代码如下所示: int c = this.md(a,b); 我们在调用委

15、托,并执行该委托所指向的方法时,本质上就是调用了其 Invoke 方法。实际上,我们可以直接调用其 Invoke 方法,代码如下所示: int c = this.md.Invoke(a,b); 另外,与 Invoke 方法对应的 BeginInvoke,是对 Invoke 方法的一个异步调用,而 EndInvoke 是异步调用完成后的处理方法,关于异步调用的说明,我们将在多线 程的章节中进行说明。 6.1.3 使用多播委托(使用多播委托(MulticastDelegate) 前面刚刚提及到 MulticastDelegate,下面我们来看一下它的应用。 有的时候,我们想要调用一个委托,但同时可

16、以执行多个方法(自定义事件中最 为常见),比如,一个工作文档生成之后,系统要将生成文档日志,而且还要被 保存到数据库中, 对于以上二个操作, 如果只想调用一个委托, 就可以顺序完成, 那么使用多播委托,就可以实现。 多播委托(MulticastDelegate)提供了一种类似于流水线式的钩子机制,只要加 载到这条流水线上的委托,都会被顺序执行。因为所有的委托都继承自 MulticastDelegate,因此所的委托都具备多播特性。 下面能过一个控制台程序来说明多播委托(MulticastDelegate)的使用方式。 案例操作案例操作 050602050602:使用多播委托使用多播委托 首先,建立一个控制台程序。在其中添加两个具备相同签名的方法: void CreateLogFile(string originalPath):用于创建日志文件 void WriteToDb(string originalPath):用于将

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 学术论文 > 毕业论文

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号