委託類似於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:感覺自己大概理解了委託和事件,但是要詳細的講清楚還是得磨練。