1. 委派可以將方法當成參數來進行傳遞
委派語法:
[public|private|protected] Delegate [void | 回傳資料型態] 委派名稱 ([參數1, 參數2,…]);
範例1.
1: public delegate int Multiply(int x, int y);
2:
3: public delegate int Timestwo(int x); // [1] 新增一個叫做timestwo的delegate,其輸入個數 = 1, 輸出個數=1
1:
2: Timestwo timestwo = delegate (int x) { return 2 * x; };
3: Multiply multiply = delegate (int x, int y) { return x * y; };
4:
5: MessageBox.Show( timestwo(5).ToString());
6: MessageBox.Show( multiply(5, 6).ToString());
範例2.
1: public delegate string SayHi(); // [2] 新增一個叫做SayHi的delegate,其輸入個數 = 0, 輸出個數=1
2: public delegate string RandSelect(); // 隨機亂數0~1, 回傳字串
3:
客戶端
1:
2:
3: RandSelect randSelect = delegate ()
4: {
5: // 定義一個SayHi變數s1, 利用匿名方法初始化之
6: SayHi s1 = delegate () { return "Hello world!"; };
7: SayHi s2 = delegate () { return "It's me, Ryan!"; };
8:
9: Random c = new Random((int)DateTime.Now.Ticks);
10: double x = c.NextDouble();
11: string str = x > 0 ? s1() : s2();
12: return string.Format("{0}, {1}",x, str);
13: };
14:
15: MessageBox.Show( randSelect() );
==================================
2. 委派是事件的基礎(event),可以利用委派來呼叫不同的事件,以便觸發其他控制項事件來完成互動性強大的應用程式。
事件語法:
public event ClickEventHandler ClickEvent;
[存取修飾詞] event 委派名稱 事件名稱(事件變數) ;
如果delegate委派是無參數,無回傳, 則註冊的Method也必須一樣是無參數,無回傳
以下設計一個無參數,無回傳的委派範例
委派名稱: void PoliceCatchThiefHandler()
事件名稱: PoliceCatchThiefEvent
警察類別
1: class Police
2: {
3: private string name;
4: public Police(string name)
5: {
6: this.name = name;
7: }
8: // 警察抓小偷委派(方法類別)
9: public delegate void PoliceCatchThiefHandler();
10: // 警察抓小偷事件(方法變數)
11: public event PoliceCatchThiefHandler PoliceCatchThiefEvent;
12:
13: public void FindBadGuys()
14: {
15: Console.WriteLine("喂! 我是{0}", name);
16: if(PoliceCatchThiefEvent != null)
17: {
18: PoliceCatchThiefEvent();
19: }
20: }
21:
22: }
小偷類別
1: class Thief
2: {
3: private string name;
4: public Thief(string name)
5: {
6: this.name = name;
7: }
8: public void RunAway()
9: {
10: Console.WriteLine("警察來了! {0}快跑", name);
11: }
12: }
客戶端
事件實體化,註冊事件
p.PoliceCatchThiefEvent += new Police.PoliceCatchThiefHandler(thief1.RunAway);
p.PoliceCatchThiefEvent += new Police.PoliceCatchThiefHandler(thief2.RunAway);
+= 右邊為實體化一個委派,該委派指向一個method,即thief1.RunAway和thief2.RunAway
+=左邊為事件變數即PoliceCatchThiefEvent ,當事件註冊後(實體化委派),PoliceCatchThiefEvent ()就可以視為一個有效method();
1: static void Main(string[] args)
2: {
3: Police p = new Police("台灣隊長"); // 美國隊長
4: Thief thief1 = new Thief("小吳"); // 小偷1
5: Thief thief2 = new Thief("阿肥"); // 小偷2
6:
7: // 實例化委託事件: 分別註冊小偷1 & 2快跑RunAway
8: // += 相當於Add_PoliceCatchThiefEvent
9: p.PoliceCatchThiefEvent += new Police.PoliceCatchThiefHandler(thief1.RunAway);
10: p.PoliceCatchThiefEvent += new Police.PoliceCatchThiefHandler(thief2.RunAway);
11:
12: // 找到壞人, 觸發事件:PoliceCatchThiefEvent
13: p.FindBadGuys();
14: Console.Read();
15:
16: }
=============================
版本2: 事件加入輸入參數:可以知道誰觸發(sender/obj)以及觸發時間(args.CurrentTime)
委派名稱: void PoliceCatchThiefHandler(object se nder, PoliceCatchThiefEventArgs args)
事件名稱: PoliceCatchThiefEvent
1: class PoliceCatchThiefEventArgs : EventArgs
2: {
3: string name;
4: DateTime dtime;
5: public string Name
6: {
7: get { return name; }
8: set { name = value; }
9: }
10: public DateTime CurrentTime
11: {
12: get { return dtime; }
13: set { dtime = value; }
14: }
15: }
警察類別
1: class Police
2: {
3: string name;
4: public Police(string name)
5: {
6: this.name = name;
7: }
8: // 警察抓小偷委派(方法類別)
9: public delegate void PoliceCatchThiefHandler(object obj, PoliceCatchThiefEventArgs args);
10: // 警察抓小偷事件(方法變數)
11: public event PoliceCatchThiefHandler PoliceCatchThiefEvent;
12: public void FindBadGuys()
13: {
14: Console.WriteLine("喂! 我是{0}", name);
15: if (PoliceCatchThiefEvent != null)
16: {
17: PoliceCatchThiefEventArgs args = new PoliceCatchThiefEventArgs();
18: args.Name = name;
19: args.CurrentTime = DateTime.Now;
20: PoliceCatchThiefEvent(this, args);
21: }
22: }
23: }
小偷類別
1: class Thief
2: {
3: string name;
4: public Thief(string name)
5: {
6: this.name = name;
7: }
8: public void RunAway(object sender, PoliceCatchThiefEventArgs args)
9: {
10: Console.WriteLine("{0} 警察 \"{1}\"來了!, \"{2}\"快跑", args.CurrentTime.ToString("yyyy/MM/dd HH:mm:ss"), args.Name, name);
11: }
12: }
客戶端
1: static void Main(string[] args)
2: {
3: Police p = new Police("台灣隊長"); // 美國隊長
4: Thief thief1 = new Thief("小吳"); // 小偷1
5: Thief thief2 = new Thief("阿肥"); // 小偷2
6:
7: // 實例化委託事件: 分別註冊小偷1 & 2快跑RunAway
8: // += 相當於Add_PoliceCatchThiefEvent
9: p.PoliceCatchThiefEvent += new Police.PoliceCatchThiefHandler(thief1.RunAway);
10: p.PoliceCatchThiefEvent += new Police.PoliceCatchThiefHandler(thief2.RunAway);
11:
12: // 找到壞人, 觸發事件:PoliceCatchThiefEvent
13: p.FindBadGuys();
14: Console.Read();
15: }
======================================
3. Delegate方法,可用於向某個Class傳遞註冊過的方法(註冊的Method的參數必須和Delegate方法完全一致)
客戶端
這個是Control類別下預設滑鼠事件
1:
2: public delegate void MouseEventHandler(object sender, MouseEventArgs e);
3: public event MouseEventHandler MouseWheel;
Form Load階段就註冊MouseWheel,利用+=右邊委派(匿名函式)
1: private void Form1_Load(object sender, EventArgs e)
2: {
3: button1.Click += delegate(System.Object o, System.EventArgs ea)
4: {
5: MessageBox.Show("訊息1:Click");
6: };
7: button1.MouseWheel += delegate(System.Object o, System.Windows.Forms.MouseEventArgs ms)
8: {
9: string str = ms.Delta > 0 ? "滾輪>0" : "滾輪<0";
10: this.Text = string.Format("訊息2:MouseWheel{0}", str);
11: };
12:
13: }
或是自訂委派名稱,注意註冊的Method的參數必須和Delegate方法完全一致
1: public delegate void MouseWheel(System.Object o, System.Windows.Forms.MouseEventArgs ms);
2: MouseWheel mousewheel = delegate (System.Object o, System.Windows.Forms.MouseEventArgs ms)
3: {
4: string str = string.Format("Time: {0}, MouseWheel{1}", DateTime.Now.ToShortTimeString(), ms.Delta > 0 ? "滾輪>0" : "滾輪<0");
5: MessageBox.Show(str);
6: };
客戶端,每按一下就新增一組事件,都指向mousewheel委派
1: private void button13_Click(object sender, EventArgs e)
2: {
3: this.button13.MouseWheel += new System.Windows.Forms.MouseEventHandler( mousewheel);
4: }
參考資料:
1. 大話設計模式, 作者: 程杰
留言列表