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

C# 程式設計利器之四:委派與事件 (上) - 委派核心概念與實戰

     編輯:關於C#

C# 委派深度解析:從函式指標到多播委派實戰

委派是 C# 特有的型別安全函式指標,也是事件機制的基石。本文涵蓋委派本質、定義語法、多播鏈結、實戰案例(運算策略、多目標輸出)、執行緒與非同步回呼應用。

一、委派本質三重身分

  1. C# 中委派是一個特殊類別(繼承自 MulticastDelegate)。
  2. 相當於 C++ 函式指標,但型別安全。
  3. 在某種程度上相當於介面(定義方法簽章契約)。

二、委派定義語法

// 關鍵字 delegate
public delegate void MyDelegate(string message);

函式簽章:回傳型別 + 參數列表。委派實例可指向任何符合此簽章的方法。

三、基礎範例:加減法運算策略

傳統寫法

class Program
{
    private static int Add(int x, int y)
    {
        int result = x + y;
        Console.WriteLine("x + y = {0}", result);
        return result;
    }

    private static int Sub(int x, int y)
    {
        int result = x - y;
        Console.WriteLine("x - y = {0}", result);
        return result;
    }

    static void Main(string[] args)
    {
        Add(8, 8);
        Sub(8, 1);
        Console.Read();
    }
}

委派重構:策略模式雛形

namespace DelegateSample1
{
    // 定義委派:回傳 int,接受兩個 int
    public delegate int OperationDelegate(int x, int y);

    public class Operator
    {
        private int _x, _y;
        public Operator(int x, int y)
        {
            this._x = x;
            this._y = y;
        }

        // 接受委派參數,執行具體運算
        public void Operate(OperationDelegate del)
        {
            del(_x, _y);
        }
    }
}

主程式使用委派

namespace DelegateSample1
{
    class Program
    {
        private static int Add(int x, int y)
        {
            int result = x + y;
            Console.WriteLine("x + y = {0}", result);
            return result;
        }

        private static int Sub(int x, int y)
        {
            int result = x - y;
            Console.WriteLine("x - y = {0}", result);
            return result;
        }

        static void Main(string[] args)
        {
            // 聲明委派物件並串聯方法(多播)
            OperationDelegate del = null;
            del += new OperationDelegate(Add);
            del += new OperationDelegate(Sub);

            Operator op = new Operator(5, 3);
            op.Operate(del); // 依序執行 Add、Sub
            Console.ReadLine();
        }
    }
}

四、委派鏈與 += / -= 運算子

  • 委派實例本質是一條委派鏈(調用清單)。
  • +=:將委派實例加入鏈結尾端。
  • -=:從鏈中移除指定委派實例。
OperationDelegate del = null;
del += new OperationDelegate(Add);   // 加入
del -= new OperationDelegate(Add);   // 移除

五、委派意義一:提升程式碼復用與彈性

Operator.Operate() 接受委派參數,可動態改變運算行為,無需修改類別本體。

六、進階實戰:多目標輸出策略

需求:輸出 0-100 數字至三種目標(Console、ListBox、文字檔)。

1. 定義委派與處理類別

namespace DelegateSample2
{
    public delegate void ShowNumberDel(object[] items);

    public class ProcessNumber
    {
        private object[] items;
        public ProcessNumber(int max)
        {
            items = new object[max];
            for (int i = 0; i < max; ++i) items[i] = i;
        }

        public void ProcessItems(ShowNumberDel show)
        {
            show(items);
        }
    }
}

2. 表單介面與三種輸出實作

表單介面示意圖

private ProcessNumber pn = null;
ShowNumberDel del = null;

private void Form1_Load(object sender, EventArgs e)
{
    pn = new ProcessNumber(100);
}

// 1. 輸出到 Console
private void ShowInConsole(object[] items)
{
    foreach (object item in items) Console.WriteLine(item);
}

// 2. 輸出到 ListBox
private void ShowInListBox(object[] items)
{
    listBox1.Items.Clear();
    foreach (object item in items) listBox1.Items.Add(item);
}

// 3. 輸出到文字檔
private void ShowInFile(object[] items)
{
    using (StreamWriter sw = new StreamWriter("Test.txt", true))
    {
        foreach (object item in items) sw.WriteLine(item);
    }
}

3. 按鈕事件綁定委派

// 單一目標
private void button1_Click(object sender, EventArgs e)
{
    pn.ProcessItems(new ShowNumberDel(ShowInConsole));
}

private void button2_Click(object sender, EventArgs e)
{
    pn.ProcessItems(new ShowNumberDel(ShowInListBox));
}

private void button3_Click(object sender, EventArgs e)
{
    pn.ProcessItems(new ShowNumberDel(ShowInFile));
}

// 多播:同時輸出到 ListBox 與檔案
private void button4_Click(object sender, EventArgs e)
{
    del += new ShowNumberDel(this.ShowInListBox);
    del += new ShowNumberDel(this.ShowInFile);
    pn.ProcessItems(del);
}

七、委派意義二:執行緒、非同步回呼、函式回呼

  • 執行緒啟動:Thread thread = new Thread(new ThreadStart(target));,ThreadStart 即無參無回傳委派。
  • 非同步模式 (APM):
    public delegate void MyDelegate(int source);
    MyDelegate del = ...;
    del.BeginInvoke(source, new AsyncCallback(CallBack), "state");
    
    private void CallBack(IAsyncResult ar)
    {
        int result = del.EndInvoke(ar);
        // 後續處理
    }
    
  • 函式回呼:將方法作為參數傳遞,於特定時機被呼叫(如排序比較、事件通知)。

八、完整測試程式碼下載

本文完整 WinForms 測試專案原始碼可從部落格附件下載。

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