很多人说,事件即委托。真的是这样吗?那么微软为何又要定义事件与委托两个概念呢?
其实事件即委托,在我看来,不如这样解释;
委托是委托,事件是封装过的委托。也就是说,事件是面向对象的产物,它只是将委托实例化的产物。
同一个方法,你可以使用委托来调用,你也可以使用事件来调用。那究竟有何不同?
转自: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);
}
}
从以上示例可以总结出:
多播是委托和事件一个很重要的特性,而事件其实是对委托的封装实例化。
