委托与事件代码详解与(Object_sender,EventArgs_e)详解
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1
委托与事件代码详解与(Object sender,EventArgs e )详解
using System;
using System.Collections.Generic;
using System.Text;
namespace @Delegate //自定义命名空间,新建控制台程序,命名后自动添加
{
// 热水器
public class Heater
{
private int temperature;
public string type = "RealFire 001"; // 添加型号作为演示
public string area = "China Xian"; // 添加产地作为演示
//声明委托
public delegate void BoiledEventHandler(Object sender, BoiledEventArgs
e);/*BoiledEventHandler 相当于一个类型(属于委托),与String 地位等同,它所声明的参数形式与后来它要包含的方法的参数形式必须是一致的,例如黄色加亮部分的方法*/
public event BoiledEventHandler Boiled; /*声明事件。相当于封装BoiledEventHandler 类型的对象(变量) Boiled ,使之在类的内部总是pravite 的,而使+=和-=的访问权限为声明时的修饰符权限*/
// 定义BoiledEventArgs 类,传递给Observer 所感兴趣的信息。//Observer 设计模式 public class BoiledEventArgs : EventArgs
{
public readonly int temperature;
public BoiledEventArgs(int temperature)
{
this.temperature = temperature;
}
}
// 可以供继承自 Heater 的类重写,以便继承类拒绝其他对象对它的监视//虚方法可以在类中覆盖重写
protected virtual void OnBoiled(BoiledEventArgs e)
{
if (Boiled != null)
{ // 如果有对象注册
Boiled(this, e); // 调用所有注册对象的方法
}
}
// 烧水。
public void BoilWater()
{
for (int i = 0; i <= 100; i++)
{
2 temperature = i;
if (temperature > 95)
{
//建立BoiledEventArgs 对象。
BoiledEventArgs e = new BoiledEventArgs(temperature);
OnBoiled(e); // 调用 OnBolied 方法
}
}
}
}
// 警报器
public class Alarm {
public void MakeAlert(Object sender, Heater.BoiledEventArgs e)
{
Heater heater = (Heater)sender; //这里是不是很熟悉呢?
//访问 sender 中的公共字段
Console.WriteLine("Alarm :{0} - {1}: ", heater.area, heater.type);
Console.WriteLine("Alarm: 嘀嘀嘀,水已经 {0} 度了:", e.temperature);
Console.WriteLine();
}
}
// 显示器
public class Display {
public static void ShowMsg(Object sender, Heater.BoiledEventArgs e)
{ //静态方法
Heater heater = (Heater)sender;
Console.WriteLine("Display :{0} - {1}: ", heater.area, heater.type);
Console.WriteLine("Display :水快烧开了,当前温度:{0}度。", e.temperature);
Console.WriteLine();s
}
}
class Program
{
static void Main()
{
Heater heater = new Heater();
Alarm alarm = new Alarm();
heater.Boiled += alarm.MakeAlert; //注册方法
heater.Boiled += (new Alarm()).MakeAlert; //给匿名对象注册方法
3
heater.Boiled += new Heater.BoiledEventHandler(alarm.MakeAlert); //也可以这么注册 heater.Boiled += Display.ShowMsg; //注册静态方法
heater.BoilWater(); //烧水,会自动调用注册过对象的方法
Console.ReadKey();
}
}
}
事件就类似于对委托变量的一个封装:
首先,事件是一个委托类型的变量,所以必须声明在类的内部,因为事件本身就是一个委托,那么自然可以将赋给委托的方法赋给事件。
而这个(封装了的委托)变量与普通的委托类型变量又有所不同:
1、不管你将它声明为public 还是protected ,它总是会在编译的时候被声明为private 。所以,如果直接对事件进行“=”赋值语法,只能在声明事件的类内部进行。
2、它封装了两个操作“+=”和“-=”,public 和protected 的访问声明仅仅是针对于对它的“+=”和“-=”操作。 这两个操作专用于在类的客户端注册方法。
如果你不使用事件,使用一个public 的委托,也可以实现上面的操作,但是类的封装性不好,在类的外部可以直接给委托变量赋值。其次就是语法会很奇怪,因为给第一个方法注册用的是“=”赋值语法(因为要进行实例化),而第二次注册方法用的是“+=”,注册语法。
使用事件的时候就解决了上面两个问题,只需要记得使用“+=”来注册方法就可以了。
实际上,委托在编译的时候确实会编译成类。因为Delegate 是一个类,所以在任何可以声明类的地方都可以声明委托。
涉及到的知识点:
Observer 设计模式简介
Observer 设计模式,Observer 设计模式中主要包括如下两类对象:
Subject :监视对象,它往往包含着其他对象所感兴趣的内容。在本范例中,热水器就是一个监视对象,它包含的其他对象所感兴趣的内容,就是temprature 字段,当这个字段的值快到100时,会不断把数据发给监视它的对象。
Observer :监视者,它监视Subject ,当Subject 中的某件事发生的时候,会告知Observer ,而Observer 则会采取相应的行动。在本范例中,Observer 有警报器和显示器,它们采取的行动分别是发出警报和显示水温。
在本例中,事情发生的顺序应该是这样的: