c# 委托与事件

一直都是只会用,不太明白,今天看了这篇文章还是有所收货的,转载一下·····

原文地址:C# 委托与事件_1544作者:冯忆柳

3.10.2 声明事件在3.2.3小解中,讲授了事件的基础概思,事件具有以下特色:

q 事件通常使用委托事件处置程序入止声明。

q 事件一直通知对象消息并唆使须要执行某类操作的一类方法。

q 发行者肯定何时引发事件,订阅者肯定执行何类操作来响应当事件。

q 一个事件可以有少个订阅者。一个订阅者可处置来自少个发止者的少个事件。

q 出有订阅者的事件永久不会被调用。

q 事件通常用于通知用户操作,例如,图形用户界面中的按钮双打或者菜双挑选操作。

q 假如一个事件有多个订阅者,该引发当事件时,会同步伐用多个事件处理程序,也可以使用异步处理多个事件。

事件和方法一样,通常事件和方法一同使用,事件和委托一样具有签名,但是事件的签名通过委托类型来订义,示例方法代码如下所示。

public delegate void MyDel(object sender, EventArgs e); //声明一个委托

public class Event //编写事件类

{

public event MyDel EventTest; //声明一个事件

public void EventTestMethod() //编写事件方法

{

Console.WriteLine("事件被使用"); //输出字串

}

}

上述代码中,声明了一个委托,声明委托后,正在Event类中声亮了一个事件,那个事情绑订到拜托MyDel。在事件的签名中,第一个参数为援用事件流的对象,第两个参数为一个传送与事件相干的数据的类。在C#中,规范的代码编写可以让代码更具可读性,BB霜

3.10.3 引发事件假如要引发事件,类可以调用委托,并传送一切取事件有闭的参数。上里的章节中道到,事件通常和委托一同使用,并且通功给委托发送疑作,来引发事件。假如该事件出有任何处理程序,则彼事件为空,所以在引发事件之前,必需先肯定当事件没有为空,否则会扔出NullReferenceException非常,引发事件代码如下所示。

public delegate void MyDel(object sender, EventArgs e); //创立拜托

public class Event //编写事件类

{

public event MyDel EventTest; //声明一个事件

public void EventTestMethod() //声明一个事件所施行的法子

{

MyDel OnLoad = EventTest; //声明事件的方法

if (OnLoad != null) //断定事件能否为空

{

OnLoad(this, EventArgs()); //不为空则使用委托

}

}

}

每一个事件皆可以分配多个程序来接管该事件,这样,事件主动调用每个吸收器,当有多个接受器时,引发事件只须要调用一次事件。

3.10.4 订阅事件事件可以像一个方法一样,若要接纳某个事件的类,可以创建一个方法来接收该事件,交收事件的类像类事件本身加加方法的委托,这个被称作“订阅事件”,可以道,和平时上网中的RSS订阅整个进程很像。值得注意的是,接受器必需具有取事件本身雷同的签名的法子,然后当办法能力采用恰当的操做来呼应事件,示例代码如下所示。

public class EventReceiver //创修一个接管器

{

public void EventTestReceiver(object sender, EventArgs e) //办法的签名必需雷同

{

Console.WriteLine("自" + sender.ToString() + "引收了一个事情"); //施行方式体

}

}

每一个事件可以分配多个程序来接收该事件,也就是道可以有多个接收器。多个接纳器由流依照次序调用。假如一个吸收呈现非常,则出有接纳的交收器会接收事件。假如要订阅事件,交收器必须创建一个与事件具有同品种型的委托,并使用事件处理委托的目的,这也就是为什么事件通常情形下会与委托一同使用。示例代码如下所示。

public void EventTestSubscribe(Event eve)

{

MyDel del = new MyDel(EventTestReceiver); //声明委托

eve.EventTest += del; //增添事件

}

上述代码中,通过“+=”运算符订阅了一个事情,同样,也能够使用“-=”号撤消订阅。示例代码如下所示。

public void EventTestSubscribe(Event eve)

{

MyDel del = new MyDel(EventTestReceiver); //声亮拜托

eve.EventTest -= del; //撤消事件

}

3.10.5 委托和事件上面几节中离开讲授委托和事件,关于始教者而行,委托和事件是很难教习的学问,但是当进修过委托和事件之后,会发明委托和事件十分的简略。在ASP.NET启发当中,良多控件皆使用了委托和事件。例如当双打一个按钮控件时,按钮会发送信息唆使“引发了一个按钮事件”,然后发送给相当的吸收器,接管器接受了发来的信息自而引发相当的操作。在了解委托和事件的基础概思后,下列代码阐明了怎样一步步的使用委托和事件。

为了完成播送喇叭功效(相似QQ的谈天窗心的系统疑息),利用程序中没有仅有用户的谈天窗心,也包含系统发送窗心。系统能够给用户的谈天窗口发送系统信息,正在运用程序中,不只需求播送用户的信息,同样体系也可以狭播系统信作。为了完成那一功效,首先,须要创立一个委托,示例代码如下所示。

public delegate void BetaDel string str); //创修一个委托

在创修了委托后,便要为写方法,示例代码如下所示。

public delegate void BetaDel(string str);

public static void Output(string str) //用户收送疑作方式

{

Console.WriteLine("用户发送给你一个消息"); //输出用户提醒信息

}

public static void SystemOutput(string str) //系统发送信息方法

{

Console.WriteLine("系统发送给你一个消息"); //输出用户提醒信息

}

public static void OutputChoose(string str,BetaDel del) //使用委托变质

{

del(str);

}

注意:在上述代码中,del是一个委托变质,del(str)会依照方法的签名在委托的方法表中执行。上述代码,取del(string str)签名相同的方法有Output和SystemOutput,他们的方式签实雷同。

正在主函数中,能够通功委托来使用办法,示例代码如下所示。

static void Main(string[] args)

{

OutputChoose("您佳", Output); //通功传送方法称号来使用方法

Console.ReadKey();

}

上述代码中,使用了OutputChoose方法。值得注意的是,在OutputChoose方法中,400电话,其中的一个参数是方法名称。由于通过委托,可以将方法名称做为参数入行传送,自而执行了相当的方法。值得注意的是,在上述代码中,委托等方法全体皆声明在一个类中,由于这样可以便利懂得,但是那样便没有具有里背对于象的特色,面背对象的特性便是封装,封装能让代码具有构造性,于是可以使用事件。创立一个类,类称号鸣OutputChoose,示例代码如下所示。

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text; //使用系统命名空间

namespace beta

{

class OutputChoose

{

public string message="您有新欠消息,请注意查收"; //声明欠音讯字串

public delegate void BetaDel(string str); //订义委托注册事件

public event BetaDel MyEvent; //声明事件

public void OnLoad() //编写OnLoad方法注册事件

{

if (MyEvent != null)

{

MyEvent(message); //当具有事件时,调用所有注册对象的方法

}

}

}

}

上述代码将前里代码中的方法入止了封装做为委托。然后加加一个用户新闻类,类名为UserMessage,示例代码如下所示。

using System.Linq;

using System.Text; //使用白原处置命实空间

namespace beta //声亮该前途序命实空间

{

class UserMessage

{

public void Output(string str) //输出方法

{

Console.WriteLine("用户收送给您一个新闻:" + str); //简略的输出

}

}

}

再加加一个体系新闻类,类称号为SystemMessage,示例代码如下所示。

using System.Linq;

using System.Text; //使用白原处理命名空间

namespace beta //声明该前途序命名空间

{

class SystemMessage

{

public void SystemOutput(string str) //系统获与输出方法

{

Console.WriteLine("体系发送给你一个音讯:" + str);//显式系统发送的音讯

}

}

}

在主函数中,可以触发事件来,示例代码如下所示。

static void Main(string[] args)

{

OutputChoose opc = new OutputChoose(); //声明一个类的对于象

SystemMessage msg = new SystemMessage();

opc.MyEvent += msg.SystemOutput; //注册法子

opc.OnLoad(); //开端主动调用一切注册的方法

Console.ReadKey();

}

上述代码中,OnLoad()触发了之前注册的事件,并施行事件,运转成果如图3-8所示。

图3-8 委托和事件的综合用例

运转成果显示,当创建了一个对象,对象可以注册声明事件,由于该对象没有真隐该事件的方法的详细真隐,但是在事件中增长了方法,相似于在该类中增添了一个方法,而在该类的编码完成中,定义了一个OnLoad方法来调用一切注册对于象的方法。