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

透過反射探究委派與事件本質:委派確實是一個類別

     編輯:關於.NET

前言

關於委派與事件的介紹網路上汗牛充棟,本文不重複基礎概念,而是從「反射」角度切入,直接觀察委派型別在運行時的成員結構,驗證「委派是一個類別、事件是委派型別的實例」這一本質認知。

反射觀察委派型別成員

delegate void DelegateDemo();
static event DelegateDemo delHandle;

static void Main() {
    delHandle += new DelegateDemo(MyDelegate_delHandle);
    
    // 取得事件的運行時型別(實際上是委派型別)
    MemberInfo[] mis = delHandle.GetType().GetMembers();
    foreach (var item in mis) {
        Console.WriteLine($"{item.Name}  {item}");
    }
}

static void MyDelegate_delHandle() {
    throw new NotImplementedException();
}

觀察結果

輸出包含以下關鍵成員(節錄):

  • Invoke - 同步呼叫委派方法
  • BeginInvoke / EndInvoke - 非同步呼叫模式
  • GetInvocationList - 取得調用清單(多播委派核心)
  • Method、Target - 封裝的方法資訊與目標物件
  • 繼承自 System.MulticastDelegate → System.Delegate → System.Object

偵錯視窗顯示委派內部成員

偵錯視窗清晰顯示:委派型別擁有完整的類別成員結構,委派確實是一個衍生自 MulticastDelegate 的密封類別。

事件的本質

程式碼中 delHandle.GetType() 取得的是事件欄位的運行時型別(即委派型別)。若改為 typeof(DelegateDemo) 結果相同。這證明:

事件就是類別中的一個委派型別實例(欄位),受 add/remove 存取器封裝,僅允許 +=/-= 操作,防止外部直接呼叫 Invoke 或覆寫調用清單。

補充:委派的協變與逆變

  • 協變:回傳型別可為衍生類別(Func<Base> ← Func<Derived>)
  • 逆變:參數型別可為基底類別(Action<Derived> ← Action<Base>)
  • 但呼叫時參數仍以委派宣告的型別為準,型別安全由編譯器保證。

結語

反射揭示了委派的類別本質與事件的封裝機制。更底層的 IL 分析(如 .ctor、Invoke 簽章)可進一步印證,但對日常開發而言,理解「委派=類別、事件=受保護的委派實例」已足夠指導正確使用模式。

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