C#委托

来源:互联网 发布:iphone 无损播放软件 编辑:程序博客网 时间:2024/06/18 04:57


Windows API经常使用C语言风格的函数指针来创建称为回调函数或简称为回调的实体。使用回调,windows开发者可以处理按钮单击、鼠标移动、菜单选择以及内存中两个实体间的双向通信。

.NET Framework里,回调功能则由更为安全和面向对象的委托(delegate)来完成。本质上来讲,委托是一个类型安全的对象,它指向程序中另一个以后会被调用的方法(或多个方法)

委托有许多用途,但它们的大多数用于事件处理和线程。


1.定义委托类型

C#中创建一个委托类型时,使用delegate关键字,委托的名称可以自由选择。例如:

public delegate intBinaryOp(int x, int y);


C#编译器处理委托类型时,它先自动产生一个派生自System.MulticasrDelegate的密封类。这个类与它的基类System.Delegate一起为委托提供必要的基础设施,以维护以后将要调用方法的列表。如下图所示,我们通过菜单栏“工具”-ILDasm”工具来查看BinaryOp委托。可以看到,为生成的BinaryOp类定义了三个公共方法:Invoke()BeginInvoke()EndInvoke()



Invoke()是核心方法,因为它用来以同步方式调用委托对象维护的方法。这里的同步就是指调用者必须等待方法调用完毕后才能继续执行。但在C#中,我们不直接调用Invoke()方法,而是使用适当地C#语法使得Invoke()在后台调用(下面会举例说明)。

BeginInvoke()EndInvoke()方法能在第二个执行线程上异步调用当前的方法。尽管.NET基础类库为多线程专门提供了整个命名空间(System.Threading),而委托顺带就提供了这一功能。

请注意,由Invoke()方法定义的参数和返回值完全匹配BinaryOp委托类型。BeginInvoke()成员前面的参数也基于BianryOp委托,但BeginInvoke()方法将总是提供最后两个参数(AsyncCallback类型和object类型),而且返回IAsyncResult接口,用于异步方法调用。最后,EndInvoke()方法的返回值类型与定义的委托返回类型相同,且总是以一个实现了IAsyncResult接口的对象作为唯一的参数。


2. 最简单的委托示例

如下面示例所示,我们定义了一个参数和返回类型都为doubleProcessDelegate委托,另外又定义了两个与委托有相同返回类型和参数列表的函数MultipleDivide。在Main函数中使用新的委托类型声明了一个委托变量process,后将Multiple函数引用赋给process委托变量。注,必须使用new关键字创建一个委托。

尽管一般在C#应用程序中不显示调用Invoke()方法,但是我们也完全可这么做,例如“Console.WriteLine("Result is {0}", process(10, 2)); ”,我们也可以写成“Console.WriteLine("Result is {0}", process.Invoke(10, 2));  

<span style="font-size:14px;">using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace Delegate{    class Program    {        //定义一个委托        delegate double ProcessDelegate(double param1, double param2);        //Multiply函数        static double Multiply(double param1, double param2)        {            return param1 * param2;        }        //Divide函数        static double Divide(double param1, double param2)        {            return param1 / param2;        }        static void Main(string[] args)        {            //声明一个ProcessDelegate委托类型的变量            ProcessDelegate process;            //初始化委托为Multiply函数的引用            process = new ProcessDelegate(Multiply);            //通过委托调用委托所引用的函数            Console.WriteLine("Result is {0}", process(10, 2));            //改变委托的为Divide函数的引用            process = new ProcessDelegate(Divide);            Console.WriteLine("Result is {0}", process(10, 2));            Console.ReadKey();        }    }}</span>


其运行结果为:




0 0
原创粉丝点击