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
參考文獻
- ^ Sturm, Oliver. Delegate calls vastly sped up in .NET 2. 2005-09-01 [2007-09-09]. (原始內容存檔於2011-07-27).
外部連結
- 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