C#委托
理解委托
委托是对方法的引用:之所以称为委托,是因为一旦被调用,就将处理“委托”给引用的方法
委托对象引用了方法。和int值赋给int变量一样,是将方法引用赋给委托对象
Processor p = new Processor();
delegeta void performCalulationDelegate();
performCalulationDelegate=p.performCalculation;
委托对象=对象.方法,方法后不用()
委托可一次引用多个方法(把它想象成方法引用集合)。一旦调用委托,所有方法都会运行。
自动化工厂例子
假定一个工厂有多种不同的机器,每个机器都有自己的系统,每个系统都有自己的关机方法,你现在的任务是将机器用的不同系统集成到一个单独控制程序中,可以实现所有机器一起关闭
StopFolding();//折叠和切割机的关机方法
FindWelding();//焊接机
PaintOff();//彩印机
用委托实现工厂控制系统
虽然每个方法的名称不同,但具有相同的“形式”,即都不获取参数,也都不返回值,这正是委托发挥作用的时候
delegate void stopMachineryDelegate();
定义好委托后,即可创建它的实例,并用+=操作符让该实例引用匹配的方法
。在类的构造器中可以这样写
class Controller
{
delegate void stopMachineryDelegate();//声明委托类型
private stopMachineryDelegate stopMachinery;//创建委托实例
//代表不同机器的字段
private FoldingMachine folder;
private WeldingMachine welder;
private PainingMachine painter;
public Controller()
{
this.stopMachinery+=folder.StopFolding;
this.stopMachinery+=welder.FindWelding;
this.stopMachinery+=painter.PaintOff;
}
...
注意只需指定方法名,不要包含任何圆括号或参数
可安全地将操作符+=用于未初始化的委托。该委托将自动初始化。还可以使用new关键字显式初始化委托,让它引用一个特定的方法
this.stopMachinery = new stopMachineryDelegate(folder.stopFolding);
可通过调用委托来调用它引用的方法,调用语法和方法完全相同
public void ShutDown()
{
this.stopMachinery();
}
委托的主要优势在于它能一次性引用多个方法,然后依次调用。也可以通过
-=来移除方法
C#事件
虽然委托允许间接调用任意数量的方法,但仍然必须显式调用委托。许多时候需要在发生某事时自动调用委托。例如,在上述例子中,一台机器过热应自动调用stopMachinery委托来关闭设备。
.Net Framework提供了事件。可定义并捕捉特定事件,并在事件发生时调用委托来进行处理。
声明事件
事件在准备作为事件来源的类中声明。事件来源类监视其环境,在发生某件事情时引发事件。
声明事件和声明字段相似。但由于事件随委托使用,所以事件的类型必须是委托
event delegateTypeNmae eventName;//delegateTypeName是委托类型名称,
//eventName是事件名称
以下是自动化工程的的StopMachineryDelegate委托。现在被转移到了新类TemperatureMonitor(温度监视器)中,也就是上面说的事件来源类
class TemperatureMonitor
{
public delegate void StopMachineryDelegate();//委托
public event StopMachineryDelegate MachineOverheating;//事件
}
订阅事件
类似于委托,事件也用+=操作符进入就绪状态
直接订阅方法:
TemperatureMonitor tempMonitor = new TemperatureMonitor();
...
tempMonitor.MachineOverheating+=folder.StopFolding;
tempMonitor.MachineOverheating+=welder.FinishWelding;
tempMonitor.MachineOverheating+=painter.PaintOff;
将委托实例与事件相关联
tempMonitor.MachineOverheating+=new 类.委托类型(this.方法)
取消订阅事件就用-=
引发事件
事件可以像方法一样通过调用来引发。引发事件后,所有和事件关联的委托会被一次调用。例如用TemperatureMonitor类声明私有方法Notify来引发MachineOverheating事件
private void Notify()
{
if(this.MachineOverheating != null)
{
this.MachineOverheating();
}
}
...
null检查是必要的,因为事件字段隐式为null,只有在一个方法使用+=操作符订阅它后,才会变成非null,防止抛出空引用异常
调用事件是要加()。如事件引发的委托要求参数,还要提供对应的实参。