C# 事件详解(二) 事件的完整声明 和 简化声明
完整 事件 声明:
模拟 顾客 到菜馆 点餐,付账。
using System; using System.Threading; namespace 事件Event { class Program { static void Main(string[] args) { 顾客 王先生 = new 顾客();//实例化一个对象 服务生 小刘 = new 服务生();//实例化一个对象 王先生.点餐事件 += 小刘.顾客点餐记录;//顾客 与 服务员 之间 订阅了事件。 //可以理解为:顾客在看菜单,服务员拿着本子在旁边等待客户点餐记录。 //这里 += 可以看完整的点餐事件,是将 服务员 的 顾客点餐记录 添加到了 点餐事件 包装里面的 点餐委托 里面。 //也就是说 点餐事件 包装着 一个 点餐委托 委托。 而外部方法添加到这个委托里面. 王先生.点餐();//调用方法。 客户点餐了。 王先生.付账();//调用方法。吃完后,客户付账。 Console.ReadKey();//按任意键继续。 } } public class 点餐参数EventArgs:EventArgs //定义类,并继承EventArgs 用于 传送 顾客点餐的 菜名 和 份量。 { public string 菜名 { get; set; }//属性 public string 份量 { get; set; }//属性 } public delegate void 点餐委托EventHandler(顾客 o,点餐参数EventArgs e);//定义委托类型. public class 顾客 //顾客 类 { private 点餐委托EventHandler 点餐委托;//声明委托对象. public event 点餐委托EventHandler 点餐事件 //完整声明 事件.包括:add 和 remove { add//事件添加器 { this.点餐委托 += value; //委托添加方法 } remove//事件移除器 { this.点餐委托 -= value;//委托移除方法 } } public double 账单 { get; set; }//属性 public void 付账()//方法 { Console.WriteLine("本次一共消费:{0} 元.",账单);//输出 } public void 坐下()//方法 { Console.WriteLine("坐下看菜单...");//输出 } public void 看菜单()//方法 { for (int i = 0; i < 5; i++)//循环 { Console.WriteLine("思考...");//输出 Thread.Sleep(1000);//将当前线程挂起指定的时间。1000毫秒 = 1秒 } if (this.点餐委托 != null)//判断委托是否不为空 { 点餐参数EventArgs e = new 点餐参数EventArgs();//声明类 并实例化 e.菜名 = "羊肉泡馍";//赋值,客户点的 菜名 e.份量 = "大份";//赋值,客户点的 份量 this.点餐委托.Invoke(this,e);//调用委托 可以简写为: 点餐委托(this,e); } } public void 点餐()//方法 { Console.ReadKey();//按任意键继续 坐下();//调用方法 看菜单();//调用方法 } } public class 服务生 //类 { public void 顾客点餐记录(顾客 o, 点餐参数EventArgs e) //事件处理器 { Console.WriteLine("这里是你点的 {0} 的 {1}.",e.份量,e.菜名);//输出 double 价格 = 10;//字段 switch (e.份量)//判断 { case "大份": 价格 = 价格 * 1.3; break; case "小份": 价格 = 价格 * 0.7; break; default: break; } o.账单 += 价格;//将得到的份量价格 添加到 客户账单内。 } } }
输出结果:
请特别注意以下事件完整声明代码:
public delegate void 点餐委托EventHandler(顾客 o,点餐参数EventArgs e);//首先先定义 委托类型 . private 点餐委托EventHandler 点餐委托;//声明 委托对象. public event 点餐委托EventHandler 点餐事件 //完整声明 事件.每个完整事件声明都包括:add 和 remove { add//事件添加器 { this.点餐委托 += value; //委托添加方法,在这里我们还不知道传递过来的方法名,所以值为: value } remove//事件移除器 { this.点餐委托 -= value;//委托移除方法,在这里我们还不知道传递过来的方法名,所以值为: value } }
简化事件声明:
using System; using System.Threading; namespace 事件简略声明 { class Program { static void Main(string[] args) { 顾客 王先生 = new 顾客();//实例化一个对象 服务员 小刘 = new 服务员();//实例化一个对象 王先生.点餐事件 += 小刘.顾客点餐记录;//顾客 与 服务员 之间 订阅了事件。 王先生.点餐();//调用方法。 客户点餐了。 王先生.付账();//调用方法。吃完后,客户付账。 Console.ReadKey();//按任意键继续。 } } public class 点餐参数EventArgs: EventArgs//定义类,并继承EventArgs 用于 传送 顾客点餐的 菜名 和 份量。 { public string 菜名 { set; get; }//属性 public string 份量 { set; get; }//属性 } public delegate void 点餐委托EventHandler(顾客 o, 点餐参数EventArgs e);//定义委托类型. public class 顾客 //顾客 类 { public event 点餐委托EventHandler 点餐事件;//简化事件 声明 public double 账单 { set; get; }//属性 public void 付账()//方法 { Console.WriteLine("本次一共消费了 {0} 元.",账单);//输出 } public void 坐下()//方法 { Console.WriteLine("坐下看菜单...");//输出 } public void 看菜单()//方法 { for (int i = 0; i < 5; i++)//循环 { Console.WriteLine("思考...");//输出 Thread.Sleep(1000);//将当前线程挂起指定的时间。1000毫秒 = 1秒 } if (点餐事件 != null)//判断事件是否不为空, 按照事件声明,这里要判断 事件包装里面的委托是否为空。 { 点餐参数EventArgs e = new 点餐参数EventArgs();//声明类 并实例化 e.菜名 = "羊肉泡馍";//赋值,客户点的 菜名 e.份量 = "大份";//赋值,客户点的 份量 this.点餐事件(this,e);//调用事件。 按照事件声明,这里要调用 事件包装里面的委托。 } } public void 点餐()//方法 { Console.ReadKey();//按任意键继续 坐下();//调用方法 看菜单();//调用方法 } } public class 服务员 { public void 顾客点餐记录(顾客 o, 点餐参数EventArgs e)//事件处理器 { Console.WriteLine("这里是你点的 {0} 的 {1}.", e.份量, e.菜名);//输出 double 价格 = 10;//字段 switch (e.份量)//判断 { case "大份": 价格 = 价格 * 1.3; break; case "小份": 价格 = 价格 * 0.7; break; default: break; } o.账单 += 价格;//将得到的份量价格 添加到 客户账单内。 } } }
输出结果:
特别注意简化声明:
public delegate void 点餐委托EventHandler(顾客 o, 点餐参数EventArgs e);//定义委托类型. public event 点餐委托EventHandler 点餐事件;//简化事件 声明
无需再声明一个委托对象。事件也无需再写 add 和 remove 语句.