《C#高級編程》指出:C/C++ 中啟動子線程傳遞全局函數指標,但 C# 純面向對象,方法不能獨立於對象存在。傳遞方法時,必須將方法細節封裝在新型對象中——委托應運而生。本文以此為線索,深挖委托實質用途與優勢。
namespace SimpleDelegate
{
public partial class Form1 : Form
{
private delegate void MyDelegete();
private MyDelegete MyObjdelegate = new MyDelegete(MyFun);
private void button1_Click(object sender, EventArgs e) { MyObjdelegate(); }
static private void MyFun() { MessageBox.Show("委托掛載的事件調用成功!"); }
}
}
定義委托類型 void MyDelegete(),實例化委托對象掛載符合簽名的方法。雖可直接調用 MyFun(),但此例僅示範基本語法。
委托類型移至類外,主類委托對象掛載其他類 ObjCls.MyFun。雖可直接實例化 ObjCls 調用公共方法,但委托提供了不同的調用控制權。
public partial class Form1 : Form
{
ObjCls objcls = new ObjCls();
private void button1_Click(object sender, EventArgs e)
{
objcls.MyObjdelegate += new ObjCls.MyDelegete(DelegateFun);
objcls.MyFun();
}
public void DelegateFun() { MessageBox.Show("次類委托所掛載的本類事件調用成功!"); }
}
public class ObjCls
{
public delegate void MyDelegete();
public MyDelegete MyObjdelegate;
public void MyFun() { MyObjdelegate(); }
}
關鍵差異:第 2 例為「類控制自身調用其他類方法」;第 3 例為「類控制其他類調用哪些方法」。這種控制反轉正是 C# 事件機制的核心。
控件定義事件:
public delegate void MyEventHander();
public event MyEventHander MyEvent;
private void button1_Click(object sender, EventArgs e) { MyEvent(); }
上層訂閱:設計器自動生成 this.userControl11.MyEvent += new Ctrleven.UserControl1.MyEventHander(this.userControl11_MyEvent);。事件本質是特殊委托,event 關鍵字使委托實例被事件視窗自動識別。
移除 event 關鍵字,改用普通委托字段,需在構造函數手動掛載:this.userControl11.MyEvent += new Ctrleven.UserControl1.MyEventHander(this.VirtualEvent);。效果相同,只是失去設計器自動識別。
常見誤區:「委托是將代碼作為參數傳入方法」。實則委托對象本身實現跨類、跨線程、跨空間傳遞方法,使用頻率遠高於作為參數傳遞。
筆者核心觀點:委托最大優勢在於兼具對象與方法二者性質。既可作為對象操控、傳遞,又可直接調用掛載方法——實現了方法的對象化。(未完待續)