委派是 C# 特有的型別安全函式指標,也是事件機制的基石。本文涵蓋委派本質、定義語法、多播鏈結、實戰案例(運算策略、多目標輸出)、執行緒與非同步回呼應用。
MulticastDelegate)。// 關鍵字 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、文字檔)。
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);
}
}
}

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);
}
}
// 單一目標
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 即無參無回傳委派。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 測試專案原始碼可從部落格附件下載。