C#中的委托和事件

1 委托

委托是寻址方法的.NET版本。它在功能上与C++中的函数指针类似,但是函数指针不是类型安全的,因为无法判断这个指针实际上是指向什么,参数和返回类型也不知道。而委托则是类型安全的类,它定义了返回类型和参数的类型。委托类既可以引用一个方法,也可以引用多个方法。

 

我们用书上的一个例子来看如何使用委托。

先是定义一个类MathOperations,它有两个静态方法,对double类型的值执行两个操作。

using System;
namespace LearnDelegate
{
	public class MathOperations
	{
		public MathOperations ()
		{
		}
		public static double MultiplyByTwo(double value)
		{
			return value * 2;
		}
		public static double Square(double value)
		{
			return value * value;
		}
	}
}


然后使用委托调用这些方法。

using System;
namespace LearnDelegate
{
	delegate double DoubleOp(double x);
	class MainClass
	{
		public static void Main (string[] args)
		{
			Console.WriteLine ("Learn Delegate!");
			DoubleOp[] operations = {
				MathOperations.MultiplyByTwo,
				MathOperations.Square
			};

			for(int i=0;i<operations.Length;i++)
			{
				Console.WriteLine ("Using operations[{0}]:",i);
				ProcessAndDisplayNumber (operations[i],2.0);
				ProcessAndDisplayNumber (operations[i],7.94);
				ProcessAndDisplayNumber (operations[i],1.414);

				Console.WriteLine ();
			}
		}

		static void ProcessAndDisplayNumber(DoubleOp action, double value)
		{
			double result = action (value);
			Console.WriteLine ("Value is {0}, result of operation is {1}",value,result);
		}
	}
}


运行结果如下:



2 事件

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

 

2.1 事件发布程序

从CarDealer类开始,它基于事件提供一个订阅。CarDealer类用event关键字定义了类型为EventHandler<CarInfoEventArgs> 的NewInfo事件。在NewCar()中,通过调用RaiseNewCarInfo方法触发NewCarInfo事件。这个方法实现了检查委托是否为空,如果不为空,就引发事件。


using System;
namespace LearnEvent
{
	public class CarInfoEventArgs: EventArgs
	{
		public CarInfoEventArgs (string car)
		{
			this.Car = car;
		}
		public string Car{ get; private set;}
	}

	public class CarDealer
	{
		public event EventHandler<CarInfoEventArgs> NewCarInfo;
		public void NewCar(string car)
		{
			Console.WriteLine("CarDealer, new car {0}", car);
			RaiseNewCarInfo(car);
		}
		protected virtual void RaiseNewCarInfo(string car)
		{
			EventHandler<CarInfoEventArgs> newCarInfo = NewCarInfo;
			if (newCarInfo != null) {
				newCarInfo (this, new CarInfoEventArgs(car));
			}
		}
	}
}


2.2 事件侦听器

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

using System;
namespace LearnEvent
{
	public 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);
		}
	}
}


3 事件的使用

现在来连接事件发布程序和订阅器。

using System;
namespace LearnEvent
{
	class MainClass
	{
		public static void Main (string[] args)
		{
			//Console.WriteLine ("Hello World!");
			var dealer = new CarDealer();
			var michael = new Consumer ("Michael");
			dealer.NewCarInfo += michael.NewCarIsHere;

			dealer.NewCar ("MAZDA");
			Console.WriteLine ();

			var sebastian = new Consumer ("Sebastian");
			dealer.NewCarInfo += sebastian.NewCarIsHere;

			dealer.NewCar ("BMW");
			Console.WriteLine ();

			dealer.NewCarInfo -= michael.NewCarIsHere;
			dealer.NewCar ("Benz");
			Console.WriteLine ();
		}
	}
}


运行结果如下:







posted @ 2017-03-29 23:57  雁回晴空  阅读(178)  评论(0编辑  收藏  举报