C# 的 委託和事件

由於本人都是自學的編程,哪裏不對的望見諒和指出。謝謝!

一、委託

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

/* 類似於 C++ 的函數指針
 * delegate <函數返回類型> <委託名> (<函數參數>)
 * 委託的參數和返回類型,都要和你要具體委託的方法要一致
 * <委託類型> <實例化名> = new <委託類型>(<註冊函數>)
 * 可以配合運算符 -, +, -=, +=,多播
 * 支持泛型 delegate <T1> <委託名><T1,T2,T3...> (T1 t1,T2 t2,T3 t3...)
 * 委託裝載的函數如果有 參數,那麼委託也要有想同的參數
 * */


namespace 委託 {
    //聲明委託
    public delegate void BuyEventHandler();
    public delegate void HasParaEventHandler(string s);

    class MrZhang {
        public void Buywater() {
            Console.WriteLine("去替小李買水");
        }
        public void Buytickets() {
            Console.WriteLine("去替小李買票");
        }
        public void Printf(string str) {
            Console.WriteLine("我再也不吃狗糧了" + str);
        }
    }

    class MrLi {
        static void Main(string[] args) {
            MrZhang mz = new MrZhang();
            BuyEventHandler buy = new BuyEventHandler(mz.Buywater);
            buy += mz.Buytickets;
            buy();
            Console.ReadKey();

            HasParaEventHandler hpeh = new HasParaEventHandler(mz.Printf);
            hpeh("哇哇哇!");
            Console.ReadKey();
        }
    }
}

 

 

 

二、事件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 事件 {
    /***********發佈器類***********/
    public class EventTest {
        private int value;
        private int count = 0;

        public delegate void NumManipulationHandler(); // 創建委託
        public event NumManipulationHandler ChangeNum; // 創建事件

        protected virtual void OnNumChanged() {
            if (ChangeNum != null) {
                Console.WriteLine("事件" + count++);
                ChangeNum(); /* 事件被觸發 */
            }
            else {
                Console.WriteLine("event not fire");
                Console.ReadKey(); /* 回車繼續 */
            }
        }

        // 構造函數
        public EventTest() {
            int n = 5;
            SetValue(n);
        }


        public void SetValue(int n) {
            if (value != n) {
                value = n;
                OnNumChanged();
            }
        }
    }


    /***********訂閱器類***********/

    public class subscribEvent {
        public void printf() {
            Console.WriteLine("event fire");
        }
        public void print() {
            Console.WriteLine("我是訂閱者類的函數");
            Console.ReadKey(); /* 回車繼續 */
        }
    }

    /***********觸發***********/
    public class MainClass {
        public static void Main() {
            EventTest e = new EventTest(); /* 實例化發佈器類,第一次沒有觸發事件,但不發出 */
            subscribEvent v = new subscribEvent(); /* 實例化訂閱器類 */
            e.ChangeNum += new EventTest.NumManipulationHandler(v.printf); /* 註冊 */
            e.ChangeNum += v.print;
            e.SetValue(7);
            e.SetValue(11);
            e.SetValue(12);
        }
    }
}

/** Console.ReadLine(); 會等待直到用戶按下回車,一次讀入一行
 * Console.ReadKey(); 則是等待用戶按下任意鍵,一次讀入一個字符。
*/

/** 該程序運行流程:首先實例化 EventTest 類時,構造函數觸發,設置 value = 5;
 * 此時 ChangeNum 爲 null,輸出 Event fire;
 * 按回車;發佈事件;
 * 此時 訂閱器類接收到信號,調用 SetValue(7) 函數;
 * 因爲此時的 ChangeNum 不爲 null 他被委託了函數 printf 和 print,調用事件委託的函數;
 * 回車;發佈事件
 * 訂閱器再次接收到信號,調用 SetValue(11) 函數;
 * ChangeNum 還是不爲 Null,再次調用 printf 和 print 函數;
 * 程序 Shutdown
 */

/* 總結:事件就是封裝過的 委託;
 * 在某個類或者結構中定義一個事件,或者直接在命名空間中定義,在該事件中裝載某些類的函數,那麼就形成了這樣一種關係
 * 擁有該事件的類成爲 發佈者類,擁有被裝載的函數類成爲 訂閱者類;
 * 當 發佈者類進行一次和 事件有關的活動後,訂閱者類的被裝載函數會被自動調用
 */

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章