理解委托
委托是对方法的引用.
平时我们调用方法是指定方法名。比如
Console.WriteLine("Hello World!");
委托对象引用了方法。就像将int值赋给int变量一样,是将方法赋给委托对象.
我们之前已经使用过委托了,比如List<T>
类的Find方法。
List类使用委托执行的操作其他方法还有Max,Min
假如我们有一间工厂,有许多台机器,其中有折叠机,焊接机、彩印机.
我们要写一个控制程序来实现停机功能,如果不适用委托可以这样写:
如果工厂采购了新机器,我们就必须修改这些代码,因为Controller类和机器是紧密联系的,这样扩展性和灵活性都不好.
声明委托
我们可以通过委托来修改上面的代码
delegate void StopMachine();//声明委托类型
声明委托使用delegate关键字。
委托定义了它所引用的方法的形式,要指定返回类型、委托名称以及任何参数.
定义好委托好,就可以创建它的示例,并用+= 操作符让该实例引用匹配的方法。
创建委托实例
下面就创建了委托实例
private StopMachine stopMachine;
delegate void StopMachine();//声明委托类型
private StopMachine stopMachine;
public Controller()
{
stopMachine += folder.StopFolding;
}
我们将机器停止的方法加到委托中,此时并没有调用方法.
注意:只需要指定方法名,不要包含圆括号或参数.
还可以用new关键字显示初始化委:
stopMachine = new StopMachine(folder.StopFolding);
可以通过调用委托来调用它引用的方法:
委托的优势在于它能够引用多个方法。
在Stop方法中调用stopMachine,将依次调用上述每一个方法。
使用-=,可以从委托中移除一个方法.
stopMachine -= painter.PaintOff;
Controller controller = new Controller();
FoldingMachine folder = new FoldingMachine();
WeldingMachine welder = new WeldingMachine();
PaintingMachine painter = new PaintingMachine();
controller.Add(folder.StopFolding);
controller.Add(welder.FinishWelding);
controller.Add(painter.PaintOff);
controller.Stop();
通过委托我们就减少了耦合性,这就是委托的一个作用.
…
…
…
Lambda表达式和委托
前面我们使用下面的方式来向委托添加方法:
stopMachine += folder.StopFolding;
对于和委托签名匹配的方法,这样写合适,但如果情况有变呢?
假如stopFolding实际签名如下:
void StopFolding(int time);//指定数秒后停机
该怎么办呢?不能在拿同一个委托处理全部三个方法了
创建方法适配器
一个解决方案是 创建另一个方法,在内部调用StopFolding:
void FinishFolding()
{
folder.StopFolding(0);//立即停机
}
然后添加到委托中:
stopMachine += folder.FinishFolding;
C#针对这种情况提供了Lambda表达式,我们可以这样使用:
stopMachine += (()=>folder.StopFolding(0));
…
…
…
事件
许多时候需要在发生某事时自动运行委托。比如,在自动化工厂中,一台机器发生了故障应该马上调用委托来关闭设备.
.NEt 提供了事件,可定义并捕捉特定的事件,并在事件发生时调用委托进行处理.
声明事件
声明事件和声明字段相似。由于事件随委托使用,所以事件的类型必须是委托,而且必须在声明前附加event前缀:
event delegateTypeName eventName
比如,我们创建一个温度监视器类,该类为监视设备温度的各种电子探头提供了接口
class TemperatureMonitor
{
public delegate void StopMachine();
public event StopMachine MachineOverheating;
...
}
要把方法添加到事件中-这个过程称为订阅事件
订阅事件
类似于委托,我们使用+=操作符订阅事件。
monitor.MachineOverheating += welder.FinishWelding;
monitor.MachineOverheating += painter.PaintOff;
类似的 我们使用-=操作符用于取消订阅
引发事件
事件可以像方法一样通过调用来引发。