搞不懂的C#中委托和事件

小白也算工作了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(); //烧水,会自动调用注册过对象的方法        } 

 //输出结果:

搞不懂的C#中委托和事件

委托和事件的区别

1、事件是委托的封装,可以理解为一种特殊的委托。

2、事件里面其实就两个方法(即add_event()和remove_event())和一个私有的委托变量,这两个方法里面分别是对这个私有的委托变量进行的合并和移除,当调用事件的+=时其实是调用的事件里面的add_event()方法,同样-=调用的是remove_event()方法。

3、在注册和注销事件上,委托可以使用=和+=来将函数注册到委托的变量上,使用-=来将函数注销。而事件则有着更严格的限制,事件只能使用+=来将函数注册到其上,使用-=来将函数注销。

结语

    这种面试题比较基础,主要考察对C#基础的了解深度,说实话在实际应用中使用的较少。当然如果需要研究.NET源码的话,则必须掌握。面试如果能答出两点,答出事件的使用场景就很不错了。希望本文对你有所帮助,同时欢迎留言和吐槽。

注:事件的案例来源于张子阳的"c#委托事件"。