Delegate (CLI)

委托（delegate）是一种类型安全的函数指针，用于通用语言运行库(CLI)。在C#中，delegate是一种class，包装了一个或多个函数指针及绑定的类实例。Delegate用来实现函数回调与事件接收（event listener）。Delegate对象可以作为参数传递给其他函数，以引用（referenced）封装在delegate对象中的函数，而无需在编译时刻就绑定被调用函数。 

一旦为委托分配了函数方法，委托将与该函数方法具有完全相同的行为。 与委托的类型特征（由返回类型和参数组成）匹配的任何方法都可以分配给该委托。

 C#例子 
声明一个delegate类型，称作SendMessageDelegate, 以一个Message类型为参数，返回类型为void: 

delegate void SendMessageDelegate(Message message);

下述代码定义了一个函数，以一个实例化的delegate类型作为形参: 

void SendMessage(SendMessageDelegate sendMessageDelegateReference)
{
  // call the delegate and any other chained delegates synchronously
  sendMessageDelegateReference(new Message("hello this is a sample message"));
}

将要封装入delegate中的一个函数的定义：
void HandleSendMessage(Message message)
{
  // the implementation for the Sender and Message classes are not relevant to this example
  Sender.Send(message);
}

函数SendMessage，以SendMessageDelegate作为委托的实例作为实参： 
SendMessage(new SendMessageDelegate(HandleSendMessage));

委托实例可以封装多个函数：
delegateType de1=fun1;
delegateType de2=fun2;
delegateType de3=de1+de2;//de3中有fun1、fun2两个函数的引用

 技术实现细节 
“委托”作为类，继承自System.MulticastDelegate（抽象类）。“委托”至少0个参数，至多32个参数，可以无返回值，也可以指定返回值类型。可以认为包含：一个类对象实例的地址（Target属性），该类的一个方法的地址（Method属性），以及另一个“委托”实例的引用（reference）。因此引用一个“委托”对象，可能实际上引用了多个“委托”的实例。“委托”对象被调用时，依次调用里面的多个“委托”的实例。这对于事件驱动的程序比较有用。  

如果“委托”封装了一个静态函数，则其内部的绑定的类对象地址为null。

可以通过Delegate类的GetInvocationList()取出这些委托，并查看其Target和Method属性，获取所引用的方法名等信息。
泛型委托
关键字Action定义了无返回值的泛型委托。Action从0个参数，至多16个参数。例如：
 public Action<int> cwdelegate; //定义一个委托cwdelegate，参数是int，无返回值。

关键字Func定义了有返回值的泛型委托。从0个参数，至多16个参数。其中最右侧的泛型类型是返回值类型。

关键字Predict定义了返回值为bool的泛型委托。

在委托实例前，不加event，那这个委托就是一个普通的委托，可以在别的函数中调用，也可以直接用对象调用。但加上event关键字之后，只能用成员函数调用

用途
一个常用的用途是事件处理。CLI定义了控件的标准的事件处理函数是一个“委托”，声明如下：
 public delegate void EventHandler(object sender, EventArgs e)
这里第一个参数是发出该事件的控件的基类型object；后一个参数是事件数据的基类型EventArgs。以Button控件类为例，它有一个属性Click，定义为一个EventHandle类型的delegate:
 public event EventHandle Click;
至此，我们对一个具体的button实例变量，可以给它的Click事件追加上一个或多个事件处理函数：
 this.button1.Click += new System.EventHandler(this.button1_click);
对于Visual Basic，上述语句的写法是：
 AddHandler button1.click, AddressOf button1_Click
参考文献

 外部链接 
MSDN documentation for Delegates
Delegates with sample code
Sun's White Paper on Delegates
Microsoft answer to Sun
Inner workings of Delegates
PerfectJPattern Open Source Project, Provides componentized i.e. context-free and type-safe implementation of the Delegates Pattern in Java

Category:子程序
Category:.NET