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

深入解析 C# 委托:編譯器如何生成委托類別

     編輯:關於C語言

當你在 C# 中宣告一個委托時,編譯器在幕後會自動生成一個完整的類別定義。以 public delegate void MyDelegate(); 為例,編譯器實際上會產生如下繼承自 System.MulticastDelegate 的類別:

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);
}

這個編譯器生成的類別包含四個核心方法:一個建構函式、Invoke、BeginInvoke 和 EndInvoke。其中建構函式與 Invoke 方法是理解委托運作機制的關鍵。

驗證編譯器生成的委托類別

我們可以使用 ILDasm.exe (IL 反組譯工具) 來檢視編譯後的組件中繼資料,確認編譯器確實生成了這樣的類別結構。下圖展示了 ILDasm 中委托類別的元數據:

ILDasm 顯示編譯器為委托生成的元數據

圖中可見,編譯器定義了一個名為 MyDelegate 的類別,繼承自 FCL (Framework Class Library) 中的 System.MulticastDelegate。所有委托類型皆繼承自 MulticastDelegate。

委托繼承體系的歷史緣由

值得注意的是:System.MulticastDelegate 繼承自 System.Delegate,後者又繼承自 System.Object。FCL 中存在兩個委托基類是有歷史原因的,這在設計上略顯遺憾。儘管所有委托類型都以 MulticastDelegate 為基類,但在某些情況下,我們仍需使用 Delegate 類別定義的方法來操作委托實例。例如 Delegate.Combine 和 Delegate.Remove 這兩個靜態方法,其參數類型為 Delegate,因為繼承關係的存在,委托實例可以直接傳入這些方法。

委托類別的可見性與定義位置

委托類別具有 Public 可見性,這取決於原始碼中委托宣告的存取修飾符。委托可以在類別內部定義 (嵌套類別),也可以在命名空間層級全域定義。簡單來說,只要可以定義類別的地方,就可以定義委托。

核心非公共欄位

由於所有委托類型都繼承 MulticastDelegate,它們共同擁有三個最重要的非公共欄位,這些欄位支撐了委托的多播調用、目標物件引用與方法指標等核心功能。

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