.NET 以委托(delegate)的形式实现了函数指针的概念。委托是类型安全的。
delegate 和类有些相似,有类型和实例之分。
delegate 是一种类型,可以在某个类定义的内部声明delegate,也可以在命名空间下声明。
使用委托(delegate):
1.定义一个委托(委托类型)
2.创建该委托类型的一个或多个实例
3.调用委托实例
* 微软并没有给委托类型和委托实例定义两个不同的术语,而是统称为委托(delegate)
1.定义一个委托(委托类型):
delegate 返回类型 委托类型名(形参列表) ;
委托的实质是用来代表一组方法,这组方法具有相同的方法签名-即委托定义中的返回类型和形参列表
只要具有和某个委托类型相符的方法签名的方法,该委托类型都可以代表。
eg: delegate long MyDelegate(int x,int y);
//委托类型MyDelegate代表那些返回值类型为long,形参列表为(int,int)的方法
2.定义委托实例:
委托类型名 委托实例名 = new 委托实例名(方法名);
定义一个委托实例,需要调用委托类型的构造函数。该构造函数只要求一个参数-一个方法名,这样就将一个委托实例和一个特定方法关联起来了。
这个被关联的方法的方法签名必须和委托类型指定的签名相一致。这个被关联方法可以是任意类的任意对象上的实例方法或静态方法。
eg: MyDelegate md = new MyDelegate(MyClass.Multiply);
//为委托类型MyDelegate定义了一个实例md,委托实例md代表了类MyClass的静态方法Multiply
//Multiply方法的方法签名必须是: long Multiply(int x,int y)
更多时候,一个委托实例与某个类对象的实例方法来关联。
3.调用委托实例:
委托实例名(实参列表);
委托实例将实参列表传给委托实例的关联方法,最后委托实例的关联方法得到执行
eg: md(2,5);
//这条语句实际上相当于执行 MyClass.Multiply(2,5)
因为执行语句一般放置在某个方法中的,所以该语句也应该放置在某个方法(把委托作为方法参数)中
eg: public static void ExecuteMethod(MyDelegate d,int x,int y)
{
long result = d(x,y); //调用委托,即调用方法MyClass.Multiply(x,y)
Console.WriteLine("The Result is {0}",result);
}
在某处调用方法ExecuteMethod:
ExecuteMethod(md,2,5);
// ExecuteMethod(md,2,5) ==> result=md(2,5) ==> result=MyClass.Multiply(2,5)
若又创建一个委托实例:
MyDelegate md2 = new MyDelegate(MySecondClass.Plus); //假定Plus方法具有相同签名
如果调用ExecuteMethod方法, ExecuteMethod(md2,1000,2555);
即 ExecuteMethod(md2,1000,2555) ==> result=md2(1000,2555) ==> result=Plus(1000,2555)
===================
示例:
using System;
namespace DelegateExample
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
//2.定义委托实例,Square是关联方法
MyDelegate d = new MyDelegate(MyClass.Square);
//3.调用委托实例,将导致委托实例的关联方法Square被执行
d(2);
Console.ReadLine();
}
}
//1.定义委托(委托类型),放置在命名空间下
delegate void MyDelegate(float x);
class MyClass
{
//委托实例d的关联方法
public static void Square(float x)
{
float result = x * x;
Console.WriteLine("{0}的平方等于:{1}", x, result);
}
}
}
====================
多点委托:
即一个委托实例关联多个方法。
单点委托中,一个委托实例代表一个方法,该委托实例调用一次,即委托的关联方法被执行一次。
多点委托中,一个委托实例代表多个方法,该委托实例调用一次,委托的多个关联方法按顺序各执行一次。
eg: MyDelegate1 d = new MyDelegate1(method1);
d += new MyDelegate1(method2);
d += new MyDelegate1(method3);
//委托类型MyDelegate1的实例d,一共关联了三个方法-method1,method2和method3
单点委托可以有返回值,但多点委托的返回值类型必须是void
其他:
定义委托类型的时候,可以使用访问修饰符 public、private和protected
多点委托被调用时,并不保证严格按关联顺序来执行各个方法,应避免编写要求严格按顺序执行方法的代码。
多点委托支持 - 和 -= 运算符(从委托实例中删除方法调用)
如果定义委托类型时,返回值类型为void,编译器自动假定该委托类型为多点委托