很多人说,事件即委托。真的是这样吗?那么微软为何又要定义事件与委托两个概念呢?
其实事件即委托,在我看来,不如这样解释;
委托是委托,事件是封装过的委托。也就是说,事件是面向对象的产物,它只是将委托实例化的产物。
同一个方法,你可以使用委托来调用,你也可以使用事件来调用。那究竟有何不同?
转自:http://blog.csdn.net/chamychen/article/details/8332929
使用委托调用时:
public delegate int Math(int a, int b); public class Test { public int Add(int a, int b) { return a + b; } } [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { Math math = new Math(new Test().Add); math(1, 2); } }
使用事件调用时:
public delegate int Math(int a, int b); public class Test { public event Math MathEvent; public int Add(int a, int b) { return a + b; } public int Operation(int a, int b) { MathEvent = Add; return MathEvent(a, b); } } [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { Test t = new Test(); t.Operation(1, 2); } }
以上示例,也许无法从面向对象的方面给你做到详细的解释。但是我们可以看出,MathEvent事件以符合Math委托签名的方法来实例化,返回的也正是Math委托的实例。这就是我提到过的事件的封装性。同样也是由于事件返回类型为委托,它也支持多播委托,即我另一篇博文《快速理解C#高级概念(一) Delegate委托》所提到的事件的方法队列。
如果以上你已经看懂,则无须看下面。不过,我还是推荐你看下面的两个示例,更清晰的理解事件和委托的区别。
使用事件时
public class Heater { private int temperature; public void BoilWater() { for (int i = 1; i <= 100; i++) { temperature = i; if (temperature > 95 && BoilEvent != null) { public class Heater { private int temperature; public void BoilWater() { for (int i = 1; i <= 100; i++) { temperature = i; if (temperature > 95 && BoilEvent != null) { //执行委托,无需知道要执行哪些方法 BoilEvent(temperature); } } } public delegate void BoilHandle(int param); public event BoilHandle BoilEvent;//封装了委托 } public class Alarm { public void MakeAlert(int param) { Console.WriteLine("Alarm:水温已经超过{0}度.",param); } } public class Display { public void ShowMsg(int param) { Console.WriteLine("Display:水已烧开,当前温度{0}度.", param); } } [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { Heater heater = new Heater(); Alarm alarm = new Alarm(); //无需实例化委托,直接针对事件添加方法 heater.BoilEvent += alarm.MakeAlert; heater.BoilEvent += new Display().ShowMsg; heater.BoilWater(); } } //执行委托,无需知道要执行哪些方法 BoilEvent(temperature); } } } public delegate void BoilHandle(int param); public event BoilHandle BoilEvent;//封装了委托 } public class Alarm { public void MakeAlert(int param) { Console.WriteLine("Alarm:水温已经超过{0}度.",param); } } public class Display { public void ShowMsg(int param) { Console.WriteLine("Display:水已烧开,当前温度{0}度.", param); } } [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { Heater heater = new Heater(); Alarm alarm = new Alarm(); //无需实例化委托,直接针对事件添加方法 heater.BoilEvent += alarm.MakeAlert; heater.BoilEvent += new Display().ShowMsg; heater.BoilWater(); } }
使用委托时:
public class Heater { private int temperature; public void BoilWater(BoilEvent b) { for (int i = 1; i <= 100; i++) { temperature = i; if (temperature > 95) { b(temperature);//此处委托无法不实例化,所以只好传递,破坏了封装性。 } } } public delegate void BoilEvent(int param); } public class Alarm { public void MakeAlert(int param) { Console.WriteLine("Alarm:水温已经超过{0}度.",param); } } public class Display { public void ShowMsg(int param) { Console.WriteLine("Display:水已烧开,当前温度{0}度.", param); } } [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { Heater heater = new Heater(); Alarm alarm = new Alarm(); Heater.BoilEvent b = new Heater.BoilEvent(alarm.MakeAlert);//委托在此处实例化 b += new Display().ShowMsg; heater.BoilWater(b); } }
从以上示例可以总结出:
多播是委托和事件一个很重要的特性,而事件其实是对委托的封装实例化。