您的位置:首页 > 编程语言 > C#

C#中的委托和事件

2012-03-15 15:43 393 查看
    委托类似于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);
}
}    那么,如何让CallDocto
b361
r事件发生时候,Doctor会调用Response方法响应呢?答案是通过将方法通过委托注册到事件中。
Doctor dct = new Doctor();
Patient pt = new Patient();
Patient.CallDoctor += new CallDoctorHander(dct.Response);// 注册方法到事件
pt.Emergency();    这样,一旦调用了Emergency方法,就会触发事件CallDoctor,然后通过委托调用注册了的方法。
    执行结果:

    


   

    PS:感觉自己大概理解了委托和事件,但是要详细的讲清楚还是得磨练。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息