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