• 浅析C#中的事件


    讲过了委托,不得不讲事件。

    事件基于委托,为委托提供了一种发布/订阅机制。

    在发生其他类或对象关注的事情时,类或对象可通过事件通知它们。发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为“订户”。

    在典型的 C# Windows 窗体或 Web 应用程序中,可订阅由控件(如按钮和列表框)引发的事件。可使用 Visual C# 集成开发环境 (IDE) 来浏览控件发布的事件,选择要处理的事件。IDE 会自动添加空事件处理程序方法和订阅事件的代码。

    事件时对委托的封装。

    事件帮助解决委托封装问题。事件位于委托的顶部,并提供封装,使得目标源只能听而不能完全控制的委托对象。

    下图显示了事件的样子: -

    理解事件:

    Button是一个类,当你点击按钮的时候,Click事件被触发。

    定时器是一个类,每毫秒tick事件被触发。

    下面通过一个例子来讲述一下事件的应用。

    定义两个类CarDealer和Consumer。CarDealer类提供了一个新车到达时触发的事件,Consumer类订阅该事件,以获得新车到达的通知。

    事件发布程序:CarDealer类提供了EventHandler类型的NewCarInfo事件。事件一般使用带两个参数的方法。第一个参数是一个对象,包含事件的发送者;第二个参数提供了事件的相关信息。

    你可能感到吃惊,没有定义委托怎么就定义事件了??其实有了泛型委托EventHandler 委托后,就不再需要委托了。

    EventHandler 的语法如下:

    public delegate void EventHandler(Object sender,TEventArgs e) where TEventArgs : EventArgs

    EventHandler定义了一个处理程序,返回void,接受两个参数。第一个参数必须是object,第二个参数是T类型,对于T有一个约束,就是它必须派生自基类EventArgs。下面代码的CarInfoEventArgs就派生自基类EventArgs.

    EventArgs是包含事件数据的类的基类,此类不包含事件数据,在事件引发时不向事件处理程序传递状态信息的事件会使用此类。如果事件处理程序需要状态信息,则应用程序必须从此类派生一个类来保存数据。事件处理程序委托的标准签名定义一个没有返回值的方法,其第一个参数的类型为 Object,它引用引发事件的实例,第二个参数从 EventArgs 类型派生,它保存事件数据。 如果事件不生成事件数据,则第二个参数只是 EventArgs 的一个实例。 否则,第二个参数为从 EventArgs 派生的自定义类型,提供保存事件数据所需的全部字段或属性。

    EventHandler 是一种预定义委托,表示事件的事件处理程序方法,它与事件是否生成事件数据无关。 如果事件不生成事件数据,则用 EventArgs 替代泛型类型参数;否则,提供自己的自定义事件数据类型并用该类型替代泛型类型参数。

    使用 EventHandler 的优点在于,如果事件生成事件数据,则无需编写自己的自定义委托代码。 此外,.NET Framework 只需一个实现就能支持 EventHandler ,这与替代泛型类型参数的事件数据类型无关。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    namespace TestEvent
    {
    	public class CarInfoEventArgs:EventArgs
    	{
    		public CarInfoEventArgs(string car)
    		{
    			this.Car = car;
    		}
    		public string Car{get; private set;}
    	}
    	public class CarDealer
    	{
    		public event EventHandlerNewCarInfo;
    		public void NewCar(string car)
    		{
    			Console.WriteLine("CarDealer. new car {0}", car);
    			if (NewCarInfo != null)
    			{
    				NewCarInfo(this, new CarInfoEventArgs(car));
    			}
    		}
    	}
    }
    

    事件监听器:Consumer类用作事件侦听器。这个类订阅了CarDealer类的事件,并定义了NewCarIsHere方法,该方法满足EventHandler委托的要求,其参数类型是object和CarInfoEventArgs.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    namespace TestEvent
    {
    	class Consumer
    	{
    		private string name;
    		public Consumer(string name)
    		{
    			this.name = name;
    		}
    		public void NewCarIsHere(object sender, CarInfoEventArgs e)
    		{
    		Console.WriteLine("{0}: car {1} is new", name, e.Car);
    		}
    	}
    }
    

    现在需要连接事件发布器和订阅器。使用“+=”创建一个订阅。使用“-=”取消了订阅。使用代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    namespace TestEvent
    {
    	class Program
    	{
    		static void Main(string[] args)
    		{
    			var dealer = new CarDealer();
    			var michael = new Consumer("Michael");
    			dealer.NewCarInfo += michael.NewCarIsHere;
    			dealer.NewCar("Mercedes");
    			var nick = new Consumer("Nick");
    			dealer.NewCarInfo += nick.NewCarIsHere;
    			dealer.NewCar("Ferrari");
    			dealer.NewCarInfo -= michael.NewCarIsHere;
    			dealer.NewCar("Toyota");
    		}
    	}
    }
    /*-------------------------------------
    输出结果:
    CarDealer. new car Mercedes
    Michael: car Mercedes is new
    CarDealer. new car Ferrari
    Michael: car Ferrari is new
    Nick: car Ferrari is new
    CarDealer. new car Toyota
    Nick: car Toyota is new
    ---------------------------------------*/
  • 相关阅读:
    Java CodeForces 1230A
    基于Lucene的全文检索实践
    错误解决:ElasticSearch SearchResponse的Hits[]总是比totalHits少一条记录
    Java CodeForces 266A
    jQuery 幻灯片插件 OwlCarousel22.3.4 使用
    由于找不到 MSVCP100.dll,无法继续执行代码。重新安装程序可能会解决此问题。
    idea 单行注释,紧跟代码第一列
    TrayPwrD3 电脑一直处于使用独显的状态
    ubuntu20.04 域名解析暂时失败
    jQuery 幻灯片插件 owl_carousev1.31 使用
  • 原文地址:https://www.cnblogs.com/sjqq/p/6918006.html
Copyright © 2020-2023  润新知