小白也算工作了5年多,居然在面试基础吃了亏。这不昨天面试回来跟小编分析,面试官问了个基础的问题“委托和事件的区别”。当面试官问到这个问题时,小白顿时有点蒙了,这个问题很熟悉啊,他们的区别是“C#中的事件是一种特殊的委托...嗯...嗯...”,然后就卡壳了,面试官就继续问下一个问题了。这篇文章将简述委托和事件及他们的区别。
要搞懂这个面试问题,还是先从概念入手吧,虽然有点枯燥,文中将用列子来说明。.
委托和事件的概念
1、委托
C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。它本质上也是一个类。它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法。
作用:可以把方法当参数传递,可以避免在程序中大量使用 If-Else(Switch)语句,同时使得程序具有更好的可扩展性。C#2.0之后出现了匿名函数和lambda表达式也是Delegate演化而来。
列子:
//还是以中国人和外国人问候的经典例子来
public class dome
{
public delegate void DelegateSayHi(string name);
/// <summary>
/// 调用委托的方法
/// </summary>
/// <param name="name"></param>
/// <param name="del"></param>
public static void Test(string name, DelegateSayHi delsay)
{
delsay(name);
}
/// <summary>
/// 汉语说你好
/// </summary>
/// <param name="name"></param>
public static void SayChinese(String name)
{
Console.WriteLine("你好," + name);
}
/// <summary>
/// 英语说你好
/// </summary>
/// <param name="name"></param>
public static void SayEnglish(String name)
{
Console.WriteLine("Hello," + name);
}
}
//调用
public static void Main()
{
dome.Test("张三",dome.SayChinese);//传递的是方法
dome.Test("liulei",dome.SayEnglish);
}
//输出:你好,张三
// Hello,liulei
上面用中英文问候的例子是一个简单使用委托的例子,大家可以进一步封装使用。
2、事件
事件由对象引发,通过我们提供的代码来处理。一个事件我们必须订阅(Subscribe)他们,订阅一个事件的含义就是提供代码,在这个事件发生时执行这些代码,这些代码称为事件处理程序。
事件是在委托类型变量前加上event关键字,其本质是用来对委托类型的变量进行封装,类似于类的属性对字段的封装。
作用:事件的使用一般通过发布者和订阅者来进行。发布者会在某一条件下触发某事件,订阅者可以通过订阅该事件,来对该事件的触发做出反应。在设计模式中的订阅者模式是最佳实践。
列子:
//以观烧水的察者模式来举例说明
// 热水器
public class Heater
{
private int temperature;
public delegate void BoilHandler(int param); //声明委托
public event BoilHandler BoilEvent; //声明事件
// 烧水
public void BoilWater()
{
for (int i = 0; i <= 100; i++)
{
temperature = i;
if (temperature > 95)
{
if (BoilEvent != null)
{ //如果有对象注册
BoilEvent(temperature); //调用所有注册对象的方法
}
}
}
}
}
// 警报器
public class Alarm
{
public void MakeAlert(int param)
{
Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:", param);
}
}
// 显示器
public class Display
{
public static void ShowMsg(int param)
{ //静态方法
Console.WriteLine("Display:水快烧开了,当前温度:{0}度。", param);
}
}
//调用
static void Main(string[] args)
{
Heater heater = new Heater();
Alarm alarm = new Alarm();
heater.BoilEvent += alarm.MakeAlert; //注册方法
heater.BoilEvent += (new Alarm()).MakeAlert; //给匿名对象注册方法
heater.BoilEvent += Display.ShowMsg; //注册静态方法
heater.BoilWater(); //烧水,会自动调用注册过对象的方法
}
//输出结果:
委托和事件的区别
1、事件是委托的封装,可以理解为一种特殊的委托。
2、事件里面其实就两个方法(即add_event()和remove_event())和一个私有的委托变量,这两个方法里面分别是对这个私有的委托变量进行的合并和移除,当调用事件的+=时其实是调用的事件里面的add_event()方法,同样-=调用的是remove_event()方法。
3、在注册和注销事件上,委托可以使用=和+=来将函数注册到委托的变量上,使用-=来将函数注销。而事件则有着更严格的限制,事件只能使用+=来将函数注册到其上,使用-=来将函数注销。
结语
这种面试题比较基础,主要考察对C#基础的了解深度,说实话在实际应用中使用的较少。当然如果需要研究.NET源码的话,则必须掌握。面试如果能答出两点,答出事件的使用场景就很不错了。希望本文对你有所帮助,同时欢迎留言和吐槽。
注:事件的案例来源于张子阳的"c#委托事件"。