C#中的委托和事件

来源:互联网 发布:酒店数据分析 编辑:程序博客网 时间:2024/06/05 20:14

    委托类似于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:感觉自己大概理解了委托和事件,但是要详细的讲清楚还是得磨练。

原创粉丝点击