.net 之美读书笔记

来源:互联网 发布:firefox flash linux 编辑:程序博客网 时间:2024/05/20 07:13

委托与事件

委托

委托的定义

委托(delegate)可以理解为函数类型,实现了函数可以当作参数传递,使程序更加灵活。下面通过代码快速熟悉委托的使用顺序。

public delegate void GreetingDelegate(string name);    class Program    {        //2.定义委托方法体        public static void EnglishGreeting(string name)        {            Console.WriteLine("Morning," + name);        }        public static void ChineseGreeting(string name)        {            Console.WriteLine("早上好," + name);        }        public static void GreetPeople(string name, GreetingDelegate markGreet)        {            //4.调用委托            markGreet(name);        }        static void Main(string[] args)        {            //3.将函数赋值给委托            GreetPeople("Jerry Zhao", EnglishGreeting);            GreetPeople("番茄赵", ChineseGreeting);            Console.ReadKey();        }

事件

事件(event):对委托的封装,保护委托不允许外部程序直接为委托赋值(会将已添加的委托丢掉)。
使用方法public event GreetingDelegate MarkGreet;

.Net事件模型

这里借助一个熟悉的例子讲诉事件模型。热水器烧水到95后,报警器报警,显示器显示。

    /// <summary>    /// 加热器    /// </summary>    public class Heater    {        private int temperature;        /// <summary>        /// 型号        /// </summary>        public string type = "RealFire 001";        /// <summary>        /// 产地        /// </summary>        public string area = "China Xian";        /// <summary>        /// 委托        /// </summary>        /// <param name="sender">被观察者(Heater)</param>        /// <param name="e">传递到观察者的参数</param>        public delegate void BoiledEnentHandler(object sender, BoiledEventArgs e);        /// <summary>        /// 初始化空函数,防止没有订阅值为null,调用报错        /// </summary>        public event BoiledEnentHandler Boiled = (sender, e) => { };        /// <summary>        /// 注意这里使用内部类,只是传递参数        /// 被观察着传入到观察者参数        /// </summary>        public class BoiledEventArgs : EventArgs        {            public readonly int temperature;            public BoiledEventArgs(int temperature)            {                this.temperature = temperature;            }        }        /// <summary>        /// 被观察者通知观察者方法        /// </summary>        /// <param name="e">参数</param>        protected virtual void OnBoiled(BoiledEventArgs e)        {            //#1多播委托            /*            foreach(Delegate d in Boiled.GetInvocationList())            {                BoiledEnentHandler boiled = (BoiledEnentHandler)d;                boiled(this, e);            }            */            //#2异常处理,一个主题有多个订阅者。订阅者一个订阅者发出异常不应该阻塞其他订阅者            /*            foreach (Delegate d in Boiled.GetInvocationList())            {                BoiledEnentHandler boiled = (BoiledEnentHandler)d;                try                {                    boiled(this, e);                }                catch (Exception ex)                {                }            }            */            //#3超时处理,发布者不应这个通知订阅者,应采用一部调用            foreach (Delegate d in Boiled.GetInvocationList())            {                BoiledEnentHandler boiled = (BoiledEnentHandler)d;                boiled.BeginInvoke(this, e, null, null);            }            //Boiled(this, e);        }        /// <summary>        /// </summary>        public void BoilWater()        {            for (int i = 0; i <= 100; i++)            {                temperature = i;                if (temperature > 95)                {                    BoiledEventArgs e = new BoiledEventArgs(temperature);                    OnBoiled(e);                }            }        }    }    /// <summary>    /// 报警器    /// </summary>    public class Alarm    {        public void MarkAlert(object sender, Heater.BoiledEventArgs e)        {            Heater heater = (Heater)sender;            Console.WriteLine("Alarm:{0}-{1}", heater.area, heater.type);            Console.WriteLine("Alarm:嘀嘀嘀,水已经{0}度", e.temperature);            Console.WriteLine();            Thread.Sleep(500);        }    }    /// <summary>    /// 显示器    /// </summary>    public class Display    {        public static void ShowMsg(object sender, Heater.BoiledEventArgs e)        {            Heater heater = (Heater)sender;            if (e.temperature == 99)            {                Thread.Sleep(2000);            }            Console.WriteLine("Display:{0}-{1}", heater.area, heater.type);            Console.WriteLine("Display:水已经{0}度", e.temperature);            Console.WriteLine();        }    }        //调用        static void Main(string[] args)        {            Heater heater = new Heater();            Alarm alarm = new Alarm();            heater.Boiled += alarm.MarkAlert;            heater.Boiled += Display.ShowMsg;            heater.BoilWater();            Console.ReadKey();        }

委托进阶

利用上面的代码介绍下多播的进阶
* 1多播委托的调用
* 2异常处理,多播中异常处理
* 3超时处理,委托的异步调用成对出现 BeginXXX,EndXXX

原创粉丝点击