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

C# 委派 入門理解:從函式簽章到多播調用

     編輯:.NET 實例教學

委派 是 C# 中「型別安全的函式指標」,它定義一個方法簽章 (參數類型、回傳類型),讓你能將符合該簽章的方法當作「物件」傳遞、儲存、動態調用。本文以通俗語言拆解委派核心概念、宣告、實例化、多播與實務應用。

核心概念:委派 = 方法簽章的型別

// 定義一個委派型別:接受 int,回傳 int
public delegate int IntOperation(int x);

這等同於定義一個「介面」:int Method(int x)。任何符合此簽章的方法 (靜態/實例、公開/私有) 都可指派給此委派變數。

基本使用流程

  1. 宣告委派型別 (通常在命名空間層級)。
  2. 撰寫目標方法 (簽章需完全相符)。
  3. 實例化委派:`new DelegateType(MethodName)` 或直接指派 (C# 2.0+ 方法群組轉換)。
  4. 呼叫委派:像呼叫方法一樣 `delegateInstance(args)`。

完整程式碼範例

using System;

public delegate int IntOperation(int x); // 1. 宣告委派型別

class Program {
    // 2. 目標方法們
    static int Double(int n) => n * 2;
    static int Square(int n) => n * n;
    static int AddTen(int n) => n + 10;

    static void Main() {
        // 3. 實例化 (方法群組轉換,等同 new IntOperation(Double))
        IntOperation op1 = Double;
        IntOperation op2 = Square;

        // 4. 呼叫
        Console.WriteLine($"Double(3) = {op1(3)}"); // 6
        Console.WriteLine($"Square(3) = {op2(3)}"); // 9

        // 5. 多播委派:串聯多個方法,依序執行,回傳最後一個結果
        IntOperation multi = Double;
        multi += Square;      // 串聯
        multi += AddTen;
        int result = multi(3); // 依序執行 Double(3)→6, Square(3)→9, AddTen(3)→13
        Console.WriteLine($"Multi(3) 最後結果 = {result}"); // 13

        // 移除
        multi -= Square;
        result = multi(3); // Double(3)→6, AddTen(3)→13
        Console.WriteLine($"移除 Square 後 = {result}"); // 13

        // 遍歷調用清單 (進階)
        foreach (IntOperation d in multi.GetInvocationList()) {
            Console.WriteLine($"  調用 {d.Method.Name}(3) = {d(3)}");
        }
    }
}

關鍵特性詳解

特性說明
型別安全編譯期檢查參數/回傳型別,不匹配直接報錯,避免執行期崩潰。
多播`+=` 串聯,`-=` 移除。調用時依序執行所有目標,回傳值為最後一個目標的回傳值。若中間拋出例外,後續不執行。
不可變性`+=`/`-=` 實際產生新的委派實例,原實例不變 (類似字串)。
目標物件綁定實例方法綁定時會捕獲 `this` (目標物件),靜態方法則無。
協變/逆變C# 支援委派回傳型別協變、參數型別逆變 (如 `Func` 可指派給 `Func`)。

內建泛型委派:`Func`、`Action`、`Predicate`

.NET Framework 3.5+ 內建常用委派,無需自行宣告:

  • Func<T1, T2, ..., TResult>:有回傳值 (最多 16 參數)。
    `Func add = (a, b) => a + b;`
  • Action<T1, T2, ...>:無回傳值 (void)。
    `Action log = s => Console.WriteLine(s);`
  • Predicate<T>:回傳 `bool`,單一參數。
    `Predicate isEven = n => n % 2 == 0;`

委派 vs 介面 vs 事件

比較點委派介面事件
本質單一方法簽章的型別多成員契約基於委派的發布/訂閱封裝
適用場景回呼、策略模式、LINQ、非同步多行為協定、依賴倒置物件狀態變更通知 (Observer)
封裝性公開調用、可任意指派僅公開介面成員僅允許 `+=`/`-=`,不可直接呼叫/清空

實務應用場景

  1. 回呼函式:非同步完成通知、排序比較器 (`Comparison`)、LINQ `Where`/`Select` 謂詞。
  2. 策略模式:執行時動態切換演算法 (如付款方式 `Func`)。
  3. 事件基礎:`event` 關鍵字封裝委派,防止外部直接 `Invoke` 或清空調用清單。
  4. 延遲執行/建構器注入:`Lazy`、`Func` 注入工廠方法。

常見誤區提醒

  • ❌ 以為委派「就是」函式指標 → ✅ 是型別安全的物件導向封裝,含目標物件參考、調用清單。
  • ❌ 多播委派回傳值以為是「全部結果」 → ✅ 僅最後一個;需全部結果請自行 `GetInvocationList()` 迴圈收集。
  • ❌ 事件就是委派 → ✅ 事件是委派的受限封裝 (只能 `+=`/`-=`),保護發布者控制權。

委派是 C# 函數式程式設計、事件驅動、非同步模型的基石。熟練掌握 `Func`/`Action`、Lambda、多播機制,能寫出更彈性、可測試、符合開閉原則的程式碼。

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