委託是一種特殊的引用類型,其設計目的是表示函數指針。全部委託都來自[System.Runtime]System.MulticastDelegate
類型,它又派生自[System.Runtime]
。委託自己是密封的(就像值類型同樣),所以不能從它們派生類型。api
對委託結構施加的限制與對枚舉器結構施加的限制同樣嚴格。委託沒有字段、事件或屬性。它們只能有兩個或四個實例方法,而且這些方法的名稱和簽名是預約義的。安全
委託的兩個強制方法是實例構造函數(.ctor)和Invoke
。實例構造函數返回void並接受兩個參數;對定義被委託方法的類型的對象引用和對被委託的託管方法的函數指針。異步
這就引出了一個問題:若是你能獲得一個函數指針,爲何你還須要委託呢?爲何不直接使用函數指針?能夠,可是須要引入函數指針類型的字段或變量來保存這些指針——函數指針類型被認爲是安全風險(由於指針值在從特定函數得到後能夠修改),而且被認爲是不可驗證的。若是一個模塊是不可驗證的,它在禁用全部安全檢查時,只能從本地驅動器以徹底信任模式執行。另外一個缺點是,在調用非託管方法時,託管函數指針不能封送到非託管函數指針,而委託能夠封送。ide
第二個強制方法(Invoke)必須與委託方法具備相同的簽名。兩個強制的方法(.ctor和Invoke)足以容許委託用於同步調用,這是在調用線程被堵塞直到被調用方法返回以前一般的方法調用。第一個方法(.ctor)建立委託實例,並將其綁定到被委託的方法。Invoke方法用於對delegate方法進行同步調用。函數
當被調用的方法在公共語言運行時爲此目的而建立的單獨線程上執行而且不阻止調用線程時,委託還能夠用於異步的調用。爲了可以被異步調用,委託必須定義兩個額外的方法:BeginInvoke
和EndInvoke
。線程
BeginInvoke
是線程啓動程序,它接受委託方法的全部參數加上另外兩個參數:類型爲[System.Runtime]
的委託System.AsyncCallback
表示在調用完成時調用的回調方法,以及選擇用於指示調用的最終狀態的對象線程。BeginInvoke
返回接口[System.Runtime]
的實例System.IAsyncResult
,攜帶做爲最後一個參數傳遞的對象,須要記住的是因爲接口、委託和對象都是引用類型,因此當我說「接受委託」或「返回接口」時,實際指的是引用。設計
若是咱們打算在調用完成時當即受到通知,則必須指定AsyncCallback
委託。在異步調用完成時調用相應的回調方法。這種事件驅動技術是對異步調用完成做出反應的最普遍使用的方法。指針
咱們能夠選擇另外一種方法來監視異步調用線程的狀態:主線程輪詢。返回的接口具備bool get_IsCompleted()
方法,當異步調用完成時,該方法返回true,咱們能夠不時地從主線程調用此方法,以肯定調用是否已經完成。code
咱們能夠調用返回接口的另外一個方法get_AsyncWaitHandle
,它返回一個等待句柄,一個[System.Runtime]System.Threading
的實例。WaitHandle類,在得到等待句柄以後,咱們能夠用任意本身喜歡的方式監視它(相似於Win32 api WaitForSingleObject和WaitForMultipleObjects的使用)。對象
若是選擇使用輪詢技術,則能夠放棄回調函數並指定null而不是System.AsyncCallback
委託實例。
EndInvoke
方法採用[System.Runtime]System.IAsyncResult
接口,由BeginInvoke
做爲其單個參數返回,並返回void。此方法等待異步調用完成,從而阻塞調用線程,所以在BeginInvoke
以後當即調用它至關於使用Invoke
的同步調用。最終必須調用EndInvoke
才能清除相應的運行時線程表條目,但應該在知道異步調用已完成時執行。
若是選擇使用輪詢技術,則能夠放棄回調函數,而指定null而不是System.AsyncCallback
委託實例。
EndInvoke
方法採用[System.Runtime]
System.IAsyncResult
接口,由BeginInvoke
返回,做爲它的單個參數,並返回void。這個方法等待異步調用完成,阻塞了調用線程,所以在BeginInvoke
以後當即調用它等同於使用Invoke
進行同步調用。最終必須調用EndInvoke
,以清除相應的運行時線程表條目,但應該在知道異步調用已經完成時執行。
委託的四個方法都是虛擬的,它們的實現由CLR自己提供的,用戶不須要邊寫這些方法的主體。在定義delegate時,咱們能夠簡單的聲明方法而不提供實現,以下所示:
.class nested public sealed auto ansi MyDelegate extends [System.Runtime]System.MulticastDelegate { .method public hidebysig specialname rtspecialname instance void .ctor( object 'object', native int 'method' ) runtime managed { // Can't find a body } // end of method MyDelegate::.ctor .method public hidebysig virtual newslot instance int32 Invoke( string s ) runtime managed { // Can't find a body } // end of method MyDelegate::Invoke .method public hidebysig virtual newslot instance class [System.Runtime]System.IAsyncResult BeginInvoke( string s, class [System.Runtime]System.AsyncCallback callback, object 'object' ) runtime managed { // Can't find a body } // end of method MyDelegate::BeginInvoke .method public hidebysig virtual newslot instance int32 EndInvoke( class [System.Runtime]System.IAsyncResult result ) runtime managed { // Can't find a body } // end of method MyDelegate::EndInvoke } // end of class MyDelegate
class Program { public delegate int MyDelegate (string s); static void Main(string[] args) { } }
參考:《Expert .NET 2.0 IL Assembler - Serge Lidin》