理解委托
委托是对方法的引用。(之所以称为委托,是因为一旦被调用,就将具体的处理“委托”给引用的方法)
委托对象引用了方法,和将int赋值给int变量一样,是将方法引用赋给委托对象。
Processor p = new Processor ();
delegate...performCalculationDelegate...;
performCalculationDelegate = p.performCalculation;//将方法引用赋给委托对象
将方法引用赋给委托时,并不是马上就运行方法。方法名之后没有圆括号,也不指定任何参数。这纯粹就是一个赋值语句。
将对Processor 对象的performCalculation方法的引用存储到委托中之后,应用程序就可通过委托来调用方法了,如下:
performCalculationDelegate (); //通过委托来调用方法
另外,委托可一次引用多个方法(把它想象成方法引用集合)。一旦调用委托,所有方法都会运行。
尚未引用有效方法的委托是不能调用的。
谓词其实就是委托。只不过它恰好返回Boolean值而已。
声明委托:
delegate void stopMachineryDelegate();
注意一下几点:
1、声明委托要使用delegate关键字。
2、委托定义了它所引用的方法的“形式”。要指定返回类型(本例是void)、委托名称(stopMachineryDelegate)以及任何参数(本例无参数);
定义好委托之后,就可创建它的实例,并用+=操作符让该实例引用匹配的方法。
class Controller
{
delegate void stopMachineryDelegate(); //声明委托类型
private stopMachineryDelegate stopMachinery; //创建委托实例
......
public Controller()
{
this. stopMachinery += folder.StopFolding;
}
........
}
上述语法只是将方法加到委托中;此时并没有实际调用方法。注意,只需指定方法名,不要包含任何圆括号或者参数。
可安全地将+=操作符用于未初始化的委托。该委托将自动初始化。还可以使用new关键字显示初始化委托。让它引用一个特定的方法。
this.StopMachinery = new stopMachineryDelegate(folder.StopFolding);
可通过调用委托来调用它引用的方法,如下:
public void ShutDown()
{
this. stopMachinery (); //通过调用委托来调用它引用的方法
}
委托的主要优势在于它能引用多个方法;使用+=操作符把这些方法添加到委托中即可。就像这样:
public Controller()
{
this. stopMachinery += folder.StopFolding;
this. stopMachinery += welder.FinishWelding;
this. stopMachinery += painter.PaintOff;
}
在Controller类的Shutdown方法中调用this. stopMachinery (),将自动依次调用上述每一个方法。
使用-=复合赋值操作符,则可从委托中移除一个方法。
如果方法与委托签名不匹配,假设StopFolding方法的签名实际是void StopFolding(int shutDownTime);
1、创建方法适配器
void FinishFolding()
{
folder. StopFolding(0);
}
2、Lambda表达式
this.stopMachinery +=(() => folder. StopFolding(0));
.NET Framework提供类事件。可定义并捕捉特定的事件,并在发生特定事件时调用委托来处理事件。
声明事件
事件在准备作为事件来源的类中声明。事件来源类监视其环境,在发生某件事情时引发事件。事件维护着方法列表,引发事件将调用这些方法。有时将这些方法称为订阅者。
声明事件的方式与字段很相似。但由于事件随同委托使用,所有事件的类型必须是委托,而且必须在声明前附加event前缀。用以下语法声明事件:
event delegateTypeName eventName //delegateTypeName是委托类型名称 eventName是事件名称
如下:定义MachineOverheating事件,该事件将调用StopMachineryDelegate
class TemperatureMonitor{
public delegate void StopMachineryDelegate();
public event StopMachineryDelegate MachineOverheating; //声明事件
..........
}
另外,要把方法添加到事件中——这个过程称为订阅事件或者向事件登记——而不是添加到事件基于的委托。
订阅事件
类似于委托,事件也用+=操作符进入就绪状态。我们使用+=操作符订阅事件。例如:
class TemperatureMonitor{
public delegate void StopMachineryDelegate();
public event StopMachineryDelegate MachineOverheating; //声明事件
..........
}
.......
TemperatureMonitor tempMonitor = new TemperatureMonitor();
......
tempMonitor.MachineOverheating += () => {folder. StopFolding(0)};
tempMonitor.MachineOverheating += welder.FinishWelding;
tempMonitor.MachineOverheating += painter.PaintOff;
tempMonitor.MachineOverheating 事件发生时,会调用所有订阅该事件的方法。
取消订阅事件
+=操作符用于订阅事件;对应地,-=操作符用于取消订阅。-=操作符将一个方法从事件的内部方法集合中移除。这个行动通常称为取消订阅事件或者从事件注销。
引发事件
和委托相似,可以把事件当作方法来调用,从而引发该事件。引发事件后,订阅了该事件的方法会依次调用。
class TemperatureMonitor{
public delegate void StopMachineryDelegate();
public event StopMachineryDelegate MachineOverheating; //声明事件
..........
private void Notify()
{
if(this.MachineryOverheating !=null)
{
this.MachineryOverheating(); //引发事件
}
}
}