委托和事件
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了委托和事件相关的知识,希望对你有一定的参考价值。
1.委托:想把一个方法做为参数进行传递,委托就是指向一个方法
2、参考 http://www.tracefact.net/CSharp-Programming/Delegates-and-Events-in-CSharp.aspx
学习委托和事件
3、声明一个委托,指向一个方法
public delegate void GreetingDelegate(string name);
public void GreetPeople(string name, GreetingDelegate MakeGreeting){
MakeGreeting(name);
}
委托的声明方式和类却完全不同,这是怎么一回事?实际上,委托在编译的时候确实会编译成类。因
为Delegate是一个类,所以在任何可以声明类的地方都可以声明委托。
4、委托不同于string的一个特性:
可以将多个方法赋给同一个委托,或者叫将多个方法绑定 到同一个委托,当调用这个委托的时候,将依次调用其所绑定的方法
使用委托可以将多个方法绑定到同一个委托变量,当调用此变量时(这里用“调用”这个词,是因为
此变量代表一个方法),可以依次调用所有绑定的方法。
我们继续思考上面的程序:实际 应用中,通常都是 GreetPeople 在一个类中,ChineseGreeting和 EnglishGreeting 在另外的类中
。现在你已经对委托有了初步了解,是时候对上面的例子做个改进了。假设我们将GreetingPeople()
放在一个叫GreetingManager的类中,那么新程序应该是这个样子的:
1 public class GreetManager 2 { 3 public event GreetingDelegate MakingGreet; 4 public void GreetPeople(string name) 5 { 6 MakingGreet(name); 7 } 8 } 9 10 public delegate void GreetingDelegate(string name); 11 public partial class Form1 : Form 12 { 13 public Form1() 14 { 15 InitializeComponent(); 16 } 17 18 private void EngishGeeting(string name) 19 { 20 MessageBox.Show(name); 21 } 22 private void ChineseGeeting(string name) 23 { 24 MessageBox.Show(name); 25 } 26 27 private void button1_Click(object sender, EventArgs e) 28 { 29 GreetManager gm = new GreetManager(); 30 gm.MakingGreet += ChineseGeeting; 31 gm.GreetPeople("你好"); 32 } 33 }
5、封装属性
如果delegate1不是一个委托类型,而是一个string类型,你会怎么做?答案是使用属性对字段进行封装。
于是,Event出场了,它封装了委托类型的变量,使得:在类的内部,不管你声明它是public还是
protected,它总是private的。在类的外部,注册“+=”和注销“-=”的访问限定符与你在声明事件
时使用的访问符相同。
1 public class GreetManager 2 { 3 public event GreetingDelegate MakingGreet; 4 public void GreetPeople(string name) 5 { 6 MakingGreet(name); 7 } 8 }
6、事件
很容易注意到:MakeGreet 事件的声明与之前委托变量delegate1的声明唯一的区别是多了一个event
关键字。看到这里,在结合上面的讲解,你应该明白到:事件其实没什么不好理解的,声明一个事件
不过类似于声明一个进行了封装的委托类型的变量而已。
1 private void button1_Click(object sender, EventArgs e) 2 { 3 GreetManager gm = new GreetManager(); 4 gm.MakingGreet += ChineseGeeting; 5 gm.GreetPeople("你好"); 6 }
7、Observer设计模式
为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其
他依赖于它的对象会被自动告知并更新。Observer模式是一种松耦合的设计模式。
1 public partial class Form1 : Form 2 { 3 public Form1() 4 { 5 InitializeComponent(); 6 } 7 8 private void button1_Click(object sender, EventArgs e) 9 { 10 Heater heater = new Heater(); 11 Alerm mAlert = new Alerm(); 12 heater.boilEvent += mAlert.MakeAlert; 13 heater.boilEvent += Display.ShowMessage; 14 heater.BoilWater(); 15 } 16 } 17 18 public class Heater 19 { 20 private int tempeter; 21 public delegate void BoilHandler(int parm); 22 public event BoilHandler boilEvent; 23 public void BoilWater() 24 { 25 for(int i=0;i<=100;i++) 26 { 27 tempeter = i; 28 if(tempeter>95) 29 { 30 //如果对象有注册 31 if(boilEvent!=null) 32 { 33 boilEvent(tempeter); 34 } 35 } 36 } 37 } 38 } 39 40 public class Alerm 41 { 42 public void MakeAlert(int param) 43 { 44 string message = "Alerm:水已经{0}度了"+ param; 45 MessageBox.Show(message); 46 } 47 } 48 49 public class Display 50 { 51 public static void ShowMessage(int param) 52 { 53 string message = "Display:当前温度:{0}" + param; 54 MessageBox.Show(message); 55 } 56 } 57
8、 .Net Framework的编码规范:
委托类型的名称都应该以EventHandler结束。
委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类
型(或继承自EventArgs)。
事件的命名为 委托去掉 EventHandler之后剩余的部分。
继承自EventArgs的类型应该以EventArgs结尾。
再做一下说明:
委托声明原型中的Object类型的参数代表了Subject,也就是监视对象,在本例中是 Heater(热水器)
。回调函数(比如Alarm的MakeAlert)可以通过它访问触发事件的对象(Heater)。
EventArgs 对象包含了Observer所感兴趣的数据,在本例中是temperature。
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Heater heater = new Heater(); Alerm mAlert = new Alerm(); heater.Boiled += mAlert.MakeAlert; heater.Boiled += Display.ShowMsg; heater.BoilWater(); } } public class Heater { private int tempeter; public string type = "001"; public string are = "china guangzhou"; public delegate void BoiledEventHandler(object sender,BoiledEventArgs e); public event BoiledEventHandler Boiled; //定义BoiledEventArgs类,传递给Observer所感兴趣的信息 public class BoiledEventArgs : EventArgs { public readonly int temperature; public BoiledEventArgs(int temp) { this.temperature = temp; } } // 可以供继承自 Heater 的类重写,以便继承类拒绝其他对象对它的监视 protected virtual void OnBoiled(BoiledEventArgs e) { if (Boiled != null) { Boiled(this, e); } } public void BoilWater() { for (int i = 0; i <= 100; i++) { tempeter = i; if (tempeter > 95) { //建立BoiledEventArgs,并调用OnBoiled方法 BoiledEventArgs e = new BoiledEventArgs(tempeter); OnBoiled(e); } } } } public class Alerm { public void MakeAlert(object sender,Heater.BoiledEventArgs e) { Heater heater = (Heater)sender; string message = "Alerm:水已经{0}度了"+e.temperature+"_" + heater.are+ "_"+heater.type; MessageBox.Show(message); } } public static class Display { public static void ShowMsg(object sender, Heater.BoiledEventArgs e) { Heater heater = (Heater)sender; string message = "Display:温度为" + e.temperature + "_" + heater.are + "_" + heater.type; MessageBox.Show(message); } }
以上是关于委托和事件的主要内容,如果未能解决你的问题,请参考以下文章