[C#] 委派 (Delegate)
Introduction
委派可以看成方法的指標,利用委派可以間接叫用方法。
委派通常主要應用於兩方面:
- 事件的驅動
- 兩個處理程序間互相呼叫(Call Back)。
Example
使用委派的三個步驟:
- 宣告委派型別。
- [ public | protected | private ] delegate 回傳值型態 委派名稱 ( 參數群 )
2. 實體化委派型別並指向相對應方法。
- 建立委派物件實體時,必須要傳入符合委派規格的方法參考
3. 使用 Invoke 方法叫用委派。
另外 : 如果要將新的方法的位置參考加入到委派物件的執行方法清單的話,必須透過 「+=」 關鍵字。
sample1
委派的基本操作
class Program {
//step1:宣告委派型別。
public delegate void MyDelegate(string name);
static void Main(string[] args) {
//step2:實體化委派型別並指向相對應方法。
// MyDelegate 委派,為沒有傳回值,
// 並且傳入參數為一個字串型別。
MyDelegate oMyDel = new MyDelegate(Show);
//.net 2.0 之後可以簡化。
MyDelegate oYourDel = Show;
//將方法加入委派物件的執行方法清單中
oYourDel += new MyDelegate(Show2);
//step3 : 使用 Invoke 方法叫用委派。
oMyDel.Invoke("MyHello!");
oYourDel.Invoke("YourHello!");
//也可簡化。
oMyDel("MyHello!");
oYourDel("YourHello!");
Console.ReadKey();
}
public static void Show(string value) {
Console.WriteLine("Show : {0}",value);
}
public static void Show2(string value) {
Console.WriteLine("Show2 : {0}",value);
}
}
結果
sample2
匿名方法 (Anonymous method) 是 .net 2.0 的新功能,當執行委派所指定的方法是一些名稱不太重要的
方法時,可以省略方法名稱。
///不使用匿名方法
public delegate MyShow(string m);
public void show(string value){
MessageBox.show(value);
}
private void Form1_Load(object sender,EventArgs e){
MyShow oMyDel = show;
oMyDel.Invoke("不使用匿名方法");
}
///使用匿名方法
public delegate void MyShow(string m)
private void Form1_Load(object sender,EventArts e){
MyShow oMyDel = delegate(string m){
MessageBox.Show(m);
};
oMyDel.Invoke("使用匿名方法");
}
sample3
多重傳送委派 是單一事件引發多個事件,利用 「-」與「+」號完成委派的新增與刪除。
其中,以下兩個方法得到的結果會是一樣的。
//直接加方法
del d = method1;
d = d + method2;
d.Invoke();
//直接加委派
del d1 = method1;
del d2 = method2;
d1 += d2;
d1.Invoke();
public delegate void Del();
private static void Show() {
Console.WriteLine("第一個呼叫");
}
private static void Show2() {
Console.WriteLine("第二個呼叫");
}
private static void Show3() {
Console.WriteLine("第三個呼叫");
}
static void Main(string[] args) {
Del oMyDel = Show;
oMyDel = oMyDel + Show2;
oMyDel += Show3;
oMyDel.Invoke();
Console.ReadKey();
}
結果
sample4
實現 CallBack
//宣告委派型別
public delegate string MyDel();
class A {
private string _name = "我是 A";
//建立與委派型別對應的方法
public string showInfo() {
return this._name;
}
public A() {
//建立委派驅動
DelDriver dirver = new DelDriver();
//建立委派實例並且指定方法
MyDel d1 = showInfo;
//呼叫驅動方法並且傳入委派物件
dirver.delDirver(d1);
}
}
class B {
private string _name = "我是 B";
//建立與委派型別對應的方法
public string showInfo() {
return this._name;
}
public B() {
DelDriver dirver = new DelDriver();
MyDel d1 = showInfo;
dirver.delDirver(d1);
}
}
class DelDriver {
public void delDirver(MyDel del) {
Console.WriteLine(del.Invoke());
}
}
class Program {
static void Main(string[] args) {
A a = new A();
B b = new B();
Console.ReadKey();
}
}
結果
sample5
利用 Lambda 運算式 完成委派,這個方法僅適用 .net 3.0 之後的版本。
「Lambda 運算式」(Lambda Expression) 是一種匿名函式,它可以包含運算式和陳述式 (Statement),而且可以用來建立委派 (Delegate) 或運算式樹狀架構型別。
所有的 Lambda 運算式都會使用 Lambda 運算子 =>,意思為「移至」。Lambda 運算子的左邊會指定輸入參數 (如果存在),右邊則包含運算式或陳述式區塊。
//宣告委派型別
public delegate void Del(string m);
static void Main(string[] args) {
//建立委派物件
//大括號裡面為匿名方法,左方 s 變數對應匿名方法,傳入。
Del oMyDel = (string s) => { Console.WriteLine(s); };
oMyDel("Hello!");
Console.ReadKey();
}
結果
Link
委派中的 Covariance 和 Contravariance (C# 程式設計手冊)
HOW TO:組合委派 (多點傳送委派) (C# 程式設計手冊)
<<後記>>
1. 使用委派建立執行緒參數
class Program { static void Main(string[] args) { StartThread(); StartThread2(); Console.ReadKey(); } static void StartThread() { //使用匿名方法,建立委派不具參數的委派 System.Threading.Thread t1 = new System.Threading.Thread (delegate() { System.Console.WriteLine("World!"); }); t1.Start(); } static void StartThread2() { //使用匿名方法,建立帶有參數的委派 System.Threading.Thread t1 = new System.Threading.Thread (delegate(object value) { System.Console.Write(value); }); t1.Start("Hello World!"); } }
<<後記2>>
在網路上不小心發現 蔡學鏞 大師有介紹 C# 的函數指標,大家可以參考一下
三小俠 小弟獻醜,歡迎指教