Delegate (CLI)

委託(delegate)是一種類型安全的函數指標,用於通用語言執行庫(CLI)。在C#中,delegate是一種class,包裝了一個或多個函數指標及繫結的類別實例。Delegate用來實現函數回呼與事件接收(event listener)。Delegate對象可以作為參數傳遞給其他函數,以參照(referenced)封裝在delegate對象中的函數,而無需在編譯時刻就繫結被呼叫函數。 [1]

一旦為委託分配了函數方法,委託將與該函數方法具有完全相同的行為。 與委託的類型特徵(由返回類型和參陣列成)匹配的任何方法都可以分配給該委託。

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

參考文獻

  1. ^ Sturm, Oliver. Delegate calls vastly sped up in .NET 2. 2005-09-01 [2007-09-09]. (原始內容存檔於2011-07-27). 

外部連結