C#中的委託和事件

    委託類似於C++中的函數指針,C#中的委託申明如下:

    delegate void MyDelegate();

    只要該委託執行的方法與委託申明的簽名一致,就能調用委託來執行該方法,例如在本例中,有個方法爲:

    void Method();那麼就可以如下調用:

    MyDelegate _delegate = new MyDelegate(Method);

    _delegate();

    這樣做的好處在於,我只需要知道調用的方法的簽名,而具體的方法調用可以等到運行的時候用委託去綁定。例如C#高級編程中的舉例,對於一個冒泡排序算法,可能是對一個整數數組排序,也可能是對對象進行排序,所以排序算法進行比較的時候就不能單純的用>=<等去判斷。不同的數組其比較的方式不一樣,那麼我只要在排序算法中使用委託,而在具體的調用時候傳遞具體的函數即可。具體請參考C#高級編程委託和事件相關章節。

    另:委託在C#中被當做是一個類。

    事件和委託結合起來使用,構成了windows界面編程的基礎。事件的申明如下:

    event MyDelegate myEvent;// 與MyDelegate相關的事件

    事件可以看成是一個委託變量,事件-委託-方法的關係是:將某個方法註冊到事件中,當事件被調用的時候,和事件相關的委託就會去調用註冊的方法。

    舉個例子:在醫院裏,醫生並不需要時時刻刻盯着病人,我們假定病人在出現問題的時候,就會通過某種方式(按鈴呼叫)通知相關的醫生。對應上面的關係,事件即是病人按鈴呼叫醫生,醫生接收到病人的呼叫並能進行處理。

    我們使用了兩個類Patient類和Doctor類。在Patient類裏面有個Emergency的方法,表示需要呼叫醫生,會觸發呼叫事件。在Doctor類中有個Response方法,表示醫生接收到病人的呼叫,採取相應的措施。因爲在實際中,Patient可能並不知道Doctor的Response方法,所以在Emergency方法裏面直接調用Response是不現實的,而且造成兩者的耦合性太高,此外,如果病人需要呼叫的不是醫生,那麼。。。混亂吧。

    下面輪到委託和事件出場了。我們定義了一個委託:

public delegate void CallDoctorHander(object sender, CallDoctorEventArgs e);

    sender表示事件的發起者(此例爲病人),e表示事件的相關信息(在此處可能是病人的相關信息,如病人姓名和房號等)。CallDoctorEvnetArgs表示與病人信息相關的類,事件觸發的時候,相關信息也進行傳遞。

// 定義一個相關事件的類,存儲病人的相關信息
    public class CallDoctorEventArgs : EventArgs
    {
        string _msg = ""; // 存儲病人的信息,例如房號和病人名稱
        public CallDoctorEventArgs()
        {

        }

        public CallDoctorEventArgs(string msg)
        {
            _msg = msg;
        }

        public string Message
        {
            set
            {
                _msg = value;
            }
            get
            {
                return _msg;
            }
        }
    }
    然後在Patient類中定義一個事件,並在Emergency方法中觸發這個事件,注意,我們並不知道誰會響應這個事件,實際上,這也不是Patient類所要關注的事情。

public class Patient
    {
        private string _name;
        private string _roomNumber;
        public Patient()
        {
            _name = "Jerry";
            _roomNumber = "1";
        }

        public Patient(string name, string roomNum)
        {
            _name = name;
            _roomNumber = roomNum;
        }

        public static event CallDoctorHander CallDoctor; // 定義事件,爲委託CallDoctorHander的變量

        // 一旦發生緊急狀況,需要調用呼叫函數
        // 對於Patient類,它並不知道具體執行的是哪個函數,只知道函數的形式
        public void Emergency()
        {
            // 調用呼叫醫生函數
            // 初始化相關的病人信息
            CallDoctorEventArgs ev = new CallDoctorEventArgs();
            ev.Message = "Patient Name: " + _name + "\nRoom Number: " + _roomNumber;
            if (CallDoctor != null)
                CallDoctor(this, ev);
        }
    }
    實際上,響應該事件的應該是Doctor中的方法。

public class Doctor
    {
        // 醫生對病人呼叫的響應
        public void Response(object sender, CallDoctorEventArgs ev)
        {
            Console.WriteLine("Sender: " + sender.ToString());
            Console.WriteLine(ev.Message);
        }
    }
    那麼,如何讓CallDoctor事件發生時候,Doctor會調用Response方法響應呢?答案是通過將方法通過委託註冊到事件中。

	    Doctor dct = new Doctor();
            Patient pt = new Patient();
            Patient.CallDoctor += new CallDoctorHander(dct.Response);// 註冊方法到事件
            pt.Emergency();
    這樣,一旦調用了Emergency方法,就會觸發事件CallDoctor,然後通過委託調用註冊了的方法。

    執行結果:

    

   

    PS:感覺自己大概理解了委託和事件,但是要詳細的講清楚還是得磨練。

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