首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

委托揭秘

     編輯:關於C#

參考來源

《框架設計(第二版)》:CLR Via C# —— 15.4 委托揭秘(P281)

基本用法範例

public class DelegateTest {
    protected delegate void MyDelegate();
    private void TestMethod() { }
    private void Method() {
        MyDelegate aMyDelegate = new MyDelegate(TestMethod);
        Method(aMyDelegate);
    }
    private void Method(MyDelegate aMyDelegate) {
        if (aMyDelegate != null) aMyDelegate();
    }
}

編譯器幕後工作

編譯器將 public delegate void MyDelegate(); 轉換為完整類別:

public class MyDelegate : System.MulticastDelegate {
    public MyDelegate(Object @object, IntPtr method);  // 建構子
    public virtual void Invoke();                      // 同步呼叫
    public virtual IAsyncResult BeginInvoke(AsyncCallback callback, object @object); // 非同步開始
    public virtual void EndInvoke(IAsyncResult result); // 非同步結束
}

可用 ILDasm.exe 驗證生成的元數據。所有委托類型繼承 MulticastDelegate,後者繼承 Delegate,再繼承 Object。FCL 歷史原因導致雙基類,需同時了解兩者。

三大核心私有欄位

欄位型別說明
_targetSystem.Object靜態方法為 null;實例方法指向調用對象(隱式 this 參數)
_methodPtrSystem.IntPtrCLR 內部整數,標識回調方法
_invocationListSystem.Object通常為 null;多播委托時引用委托陣列

建構子機制

原始碼傳遞 TestMethod,編譯器解析為物件引用與方法標識 IntPtr,分別存入 _target、_methodPtr,並將 _invocationList 設為 null。每個委托物件實際封裝一個方法及其調用對象。

Invoke 呼叫機制

代碼 aMyDelegate(); 編譯器轉為 aMyDelegate.Invoke();。Invoke 簽名與委托一致,內部使用 _target、_methodPtr 對指定物件呼叫方法。ILDasm 可驗證生成的 IL 代碼確實呼叫 Invoke。

總結

委托表面簡單,實則編譯器與 CLR 做大量幕後工作隱藏複雜性。理解其內部結構有助於更好地使用委托。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved