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

C# 語言規范解讀:委托 —— 類型安全的函數指針

     編輯:關於C語言

前言:委托的定位

委托適用於其他語言需用函數指針解決的場景,但委托是面向對象且類型安全的。它是 C# 事件模型、回調、異步編程、LINQ 查詢的基石。本文對應規范第 1.10 節「委托」。

核心機制

  • 委托聲明 定義一個繼承自 `System.Delegate` 的類
  • 委托實例 封裝一個調用列表 (一個或多個可調用實體):
    • 實例方法:`(對象實例, 方法)`
    • 靜態方法:`(方法)`
  • 調用:用一組參數調用委托實例 → 列表中每個可調用實體依次以相同參數被調用

關鍵特性:匿名調用

委托實例不知道也不關心封裝方法所屬的類型、訪問性、靜態與否,只關心簽名兼容性。這使委托極適合「匿名調用」—— 強大的解耦能力。

三步驟:聲明、實例化、調用

1. 聲明

delegate void SimpleDelegate(); // 無參、無返回值

2. 實例化


class Test
{
    static void F() => Console.WriteLine("Test.F");
    
    static void Main()
    {
        // 創建委托實例綁定靜態方法
        SimpleDelegate d = new SimpleDelegate(F);
        // 或簡寫 (C# 2.0+ 方法組轉換)
        SimpleDelegate d2 = F;
        
        // 3. 調用
        d(); // 輸出 "Test.F"
    }
}

實際價值:高階函數 MultiCall


// 不關心具體方法,只關心簽名兼容
void MultiCall(SimpleDelegate d, int count)
{
    for (int i = 0; i < count; i++)
        d();
}

// 使用
MultiCall(F, 3); // 執行 3 次 F
MultiCall(() => Console.WriteLine("Lambda!"), 2); // 匿名方法/Lambda

委托 vs 函數指針

特性C/C++ 函數指針C# 委托
類型安全無 (僅簽名匹配,易崩潰)編譯期強檢查
面向對象否是 (繼承 Delegate/MulticastDelegate)
綁定目標僅函數地址實例+方法 / 靜態方法
多播不支持內建支持 (+=/-= 組合調用列表)
捕獲上下文需手動傳遞上下文指針閉包/匿名方法自動捕獲
垃圾回收手動管理托管,自動生命週期

多播委托


SimpleDelegate d = F;
d += G; // 組合
d += () => Console.WriteLine("Lambda");
d(); // 依次調用 F, G, Lambda

d -= G; // 移除
// 調用列表順序 = 添加順序,異常會中斷後續調用

現代演進:Func/Action + Lambda

C# 3.0+ 引入預定義泛型委托,絕大多數場景無需自定義 `delegate`:


// 無返回:Action, Action, Action...
Action log = () => Console.WriteLine("Log");
Action logMsg = msg => Console.WriteLine(msg);

// 有返回:Func, Func...
Func add = (a, b) => a + b;
Func getTime = () => DateTime.Now.ToString();

// 異步/任務
Func asyncOp = async () => await DoWork();

總結

委托是 C# 類型系統中「可執行代碼」的一等公民表示。它以類型安全、面向對象、多播、閉包捕獲特性,完美替代了函數指針,並構成了事件、異步、LINQ、函數式編程的基礎設施。理解「聲明定義類、實例封裝調用列表、調用遍歷列表」的核心模型,是掌握 C# 高級編程的關鍵。

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