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

C# 3.0 進階基石:委托與事件深度解析(上)

     編輯:關於C語言

前言:為什麼在 C# 3.0 學習前要回顧委托?

C# 3.0 引入的 Lambda 表達式、LINQ、擴展方法等特性,底層無一不建立在委托與事件機制之上。理解委托的內存模型、多播鏈表、編譯器生成細節,是掌握現代 C# 函數式編程風格的鑰匙。

委托本質:類型安全的函數指針

C 語言函數指針僅存地址,缺乏參數/返回類型檢查。.NET 委托封裝三要素:

  1. 目標方法簽名(參數列表、返回類型)
  2. 目標對象實例(靜態方法為 null)
  3. 調用列表(支持多播)

聲明與編譯器生成


// 源碼
public delegate int Calculate(int x, int y);

// 編譯器生成(等價)
[Serializable]
public sealed class Calculate : MulticastDelegate
{
    public Calculate(object @object, IntPtr method) { ... }
    public virtual int Invoke(int x, int y) { ... }
    public virtual IAsyncResult BeginInvoke(int x, int y, AsyncCallback cb, object obj) { ... }
    public virtual int EndInvoke(IAsyncResult result) { ... }
}

關鍵點:

  • 繼承 MulticastDelegate → 自動擁有調用列表管理能力
  • Invoke 同步調用、BeginInvoke/EndInvoke 異步模式(APM)
  • 編譯器自動生成,開發者不可手寫繼承 Delegate 的類

委托核心成員解析

成員類型用途
MethodMethodInfo獲取目標方法元數據(名稱、參數、返回類型)
Targetobject目標實例(靜態方法為 null)
GetInvocationList()Delegate[]獲取調用鏈中每個單播委托,支持逐個調用/異常隔離
Combine / Removestatic Delegate多播鏈表添加/移除(+= / -= 底層調用)

多播委托調用語義


Action a = () => Console.WriteLine("1");
a += () => Console.WriteLine("2");
a += () => throw new Exception("錯誤");
a += () => Console.WriteLine("3");

a(); 
// 輸出:1, 2, 然後拋出異常,"3" 不會執行
// 返回值:僅保留最後一個委托的返回值

警示:多播委托異常會中斷後續調用,需用 GetInvocationList() 手動遍歷捕獲異常。

實戰:動態策略模式


public delegate double CalcStrategy(double a, double b);

public class Calculator
{
    public CalcStrategy Strategy { get; set; } = (a,b) => a + b;
    
    public double Execute(double a, double b) => Strategy(a, b);
}

// 運行時切換策略
var calc = new Calculator();
calc.Strategy = (a,b) => a - b; // 減法
calc.Strategy = (a,b) => a * b; // 乘法
calc.Strategy = Math.Pow;       // 靜態方法也可

總結

委托是 C# 函數一等公民的基石:類型安全、面向對象、支持多播、編譯器自動生成調用基礎設施。下一篇將深入事件模式、編譯器生成的 add/remove 方法、以及如何通過事件實現鬆耦合通知機制,為 Lambda 表達式與 LINQ 鋪路。

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