close

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:        }

image

=============================

版本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:        }

image

======================================

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:    }

image

或是自訂委派名稱,注意註冊的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. 大話設計模式, 作者: 程杰

2. 如何 使用 委派 Delegate / 事件 event

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 me1237guy 的頭像
    me1237guy

    天天向上

    me1237guy 發表在 痞客邦 留言(2) 人氣()