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);
}
}
}
现在来连接事件发布程序和订阅器。
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 ();
}
}
}
运行结果如下: