摘要:物件導向系列菜單10-『委派(Delegate)』
~哀悼~ 給予不幸的人。
什麼是委派
白話文來說,委派方法是一種參考型別(Type),可以用來將方法當做引數傳遞給其他方法。
圖為委派型別的宣告範例
為什麼要用委派
從類別的設計者來看,在設計類別時,可能會碰到某個方法需要額外處理,但又不想把該處理想在這個類別裡因為有可能變化很多,又或是無法預先得知處理的規則。
(註:這部份主要參考Huan-Lin的文章)
簡單用個情境來說明委派的用法
維京老大有一艘戰船,這艘船是老大專門買來給小弟用去打劫的(主要原因是因為老大怕死和麻煩),為了維護自身利益,老大定了一個用船契約範本,上面定了兩個規定分別為『回傳string型別』與『輸入一個string型別的參數』,小弟需要自行寫一份參考老大契約範本的契約,裡面一定要符合這兩項規定,小弟才能拿這份契約去和老大借船,然後執行自行寫的打劫計畫。依上述的模擬情境來寫個程式碼來看看 ~首先先宣告一個委派方法,這就是維京老大所寫的契約範本,上面規定,小弟的契約裡需要符合兩個條件分別為『回傳string型別』與『輸入一個string型別的參數』。
然後小弟1這時想要和老大借船來幹一票大的~~ ,所以開始寫契約,如下,有沒有符合老大的範本要求呢??
『回傳string型別』與『輸入一個string型別的參數』,嗯都有,拿去給老大看應該會答應!
{
//這邊可以小弟可自訂自已的攻擊計畫
//反正最後有回傳黃金(string型別)給老大就好
Console.WriteLine(str);
return "給老大的黃金" ;
}
這時小弟1就跑去和老大借船。
老大 : 嗯很好有符合,~ 努力去(為我)打劫吧!
老大 : 嗯很好有符合,~ 努力去(為我)打劫吧!
{
//C# 2.0寫法
Attack attack_plan = Attack_Plan1;
GoToAttackWithBattleShip(attack_plan, "Attack");
}
private void GoToAttackWithBattleShip(Attack attack_plan, string str)
{
textBox1.Text = attack_plan(str);
}
這時又來個小弟2,他也想要船,但他沒注意到契約範本規則,然後建立了下面的契約,不符合『傳入一個string型別的參數』。
{
return "給老大的黃金" ;
}
這時它還是傻傻的跑去向老大借船,結果…
{
//C# 2.0寫法
Attack attack_plan = Attack_Plan2;
GoToAttackWithBattleShip(attack_plan, "Attack");
}
多重委派 delegate物件具有一種屬性,就是可以使用+運算子將多個物件指派給一個委派執行的個體。 由於維京老大越來越懶了,他開始討厭一次來一個的模式,於是他就開始使用『多重委派』,出船一次的就可以帶小弟1…2…3 一起去打劫,打完後在回來,維京老大笑哈哈~。
範例程式碼如下。
public delegate string Attack (string str);
private void button1_Click( object sender, EventArgs e)
{
//C# 2.0寫法
Attack attack_plan = Attack_Plan1;
attack_plan += Attack_Plan2;
GoToAttackWithBattleShip(attack_plan, "Attack" );
}
//顯示Page的文字
private void GoToAttackWithBattleShip( Attack attack_plan, string str)
{
textBox1.Text = attack_plan(str);
}
public string Attack_Plan1( string str)
{
//這邊可以小弟可自訂自已的攻擊計畫
//反正最後有回傳黃金(string型別)給老大就好
Console .WriteLine("小弟1執行打劫活動囉~~~" );
return "給老大的黃金" ;
}
public string Attack_Plan2( string str)
{
Console .WriteLine("小弟2執行打劫活動囉~~~" );
return "給老大的黃金" ;
}
注意
1.它會依順序來呼叫
2.只有相同型別的委派才能加以結合
3.委派清單不會過濾掉重覆的方法。
我們將上面程式碼再運用+運算子將Attack_Plan1再加一次。則結果如下。
{
//C# 2.0寫法
Attack attack_plan = Attack_Plan1;
attack_plan += Attack_Plan2;
attack_plan += Attack_Plan1;
GoToAttackWithBattleShip(attack_plan, "Attack" );
}
參考資料