美文网首页C#.Net微说集Asp.net开发
第一部分:C#语言基础----委托和事件

第一部分:C#语言基础----委托和事件

作者: 张中华 | 来源:发表于2017-11-08 23:39 被阅读56次

    第3章 C#中的委托和事件

    3.1 理解委托

    3.1.1 将方法作为方法的参数

    委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使程序具有更好的可扩展性。
    使用方式:
    1.首先定义两个方法

     public void EnglishGreeting(string name)
            {
                Console.WriteLine("Morning, " + name);
            }
            public void ChineseGreeting(string name)
            {
                Console.WriteLine("早上好, " + name);
            }
    

    2.定义一个委托

    public delegate void GreetDelegate(string name);
    

    3.定义一个使用委托的方法

    //注意此方法,它接受一个GreetingDelegate类型的方法作为参数
            public static void GreetPeople(string name, GreetDelegate MakeGreeting)
            {
                MakeGreeting(name);
            }
    

    4.使用委托方法

    static void Main(string[] args)
            {
                GreetPeople("zzh",EnglishGreeting);
                GreetPeople("中华",ChineseGreeting);
                Console.ReadLine();
            }
    

    委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使程序具有更好的可扩展性。
    第二种使用委托的方式:



    第三种方式,绕过GreetPeople方法(比较喜欢这种方法)



    既然委托可以绑定一个方法,那么也应该有办法取消对方法的绑定,很容易想到,这个语法是“-=”。

    3.2 事件的由来

    使用事件不仅能获得比委托更好的封装性,还能限制含有事件的类型的能力。
    1.首先,准备两个方法:

    public static void EnglishGreeting(string name)
            {
                Console.WriteLine("Morning, " + name);
            }
            public static void ChineseGreeting(string name)
            {
                Console.WriteLine("早上好, " + name);
            }
    

    2.然后呢,准备一个一个委托类型

    //定义委托,它定义了可以代表的方法的类型
        public delegate void GreetingDelegate(string name);
    

    3.接着准备一个事件,来使用这个委托类型(此处放在一个GreepManager类中)

     public class GreetingManager
        {
           //声明事件
           public event GreetingDelegate MakeGreet;
           public void GreetPeople(string name)
           {
               MakeGreet(name);
           }
        }
    

    4.最后使用这个事件方法

    static void Main(string[] args)
            {
    
                GreetingManager gm = new GreetingManager();
                gm.MakeGreet += EnglishGreeting;//注意此处,并没用使用先赋值的方式
                gm.MakeGreet += ChineseGreeting;
                gm.GreetPeople("zzh");
            }
    
    3.2.2 限制类型能力

    使用事件不仅能获得比委托更好的封装性,还能限制含有事件的类型的能力。这是什么意思呢?它的意思是说:事件应该由事件的发布者触发,而不应该由事件的客户端(客户程序)来触发。
    1.首先定义一个委托

    // 定义委托
        public delegate void NumberChangedEventHandler(int count);
    

    2.然后呢,定义一个事件发布者

    // 定义事件发布者
        public class Publishser
        {
            private int count;
            public NumberChangedEventHandler NumberChanged; // 声明委托变量
            public void DoSomething()
            {
                // 在这里完成一些工作 ...
                if (NumberChanged != null)
                { // 触发事件
                    count++;
                    NumberChanged(count);
                }
            }
        }
    

    3.接着定义一个事件接收者

    // 定义事件订阅者
        public class Subscriber
        {
            public void OnNumberChanged(int count)
            {
                Console.WriteLine("Subscriber notified: count = {0}", count);
            }
        }
    

    4.最后就是使用事件了

    class Program
        {
            static void Main(string[] args)
            {
                Publishser pub = new Publishser();
                Subscriber sub = new Subscriber();
                pub.NumberChanged += new NumberChangedEventHandler(sub.OnNumberChanged);
                pub.DoSomething(); // 应该通过DoSomething()来触发事件
                pub.NumberChanged(100); // 也可以被这样直接调用,对委托变量的不恰当使用
                Console.ReadLine();
            }
        }
    

    理解:首先声明发布者和接收者,然后为发布者里的委托变量赋值,调用订阅者的方法,使用发布者里面的方法,启动事件的发生,然后……有点绕,再看看吧……
    这里还有一个约定俗称的规定,就是订阅事件的方法的命名,通常为“On事件名”,比如这里的OnNumberChanged。

    3.4 .NET框架中的委托和事件

    假设有个高档的热水器,当水温超过95度的时候:一、扬声器会开始发出语音,告诉你水的温度;二、液晶屏也会改变水温的显示,以提示水已经快烧开了。现在需要写个程序来模拟这个烧水的过程,我们将定义一个类来代表热水器,将它取名为Heater,它有代表水温的字段temperature,当然,还有必不可少的水加热方法BoilWater(),一个发出语音警报的方法MakeAlert(),一个显示水温的方法,ShowMsg()。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace TestEventAndDelegate
    {
        public class Heater
        {
            private int temperature; // 水温
            // 烧水
            public void BoilWater()
            {
                for (int i = 0; i <= 100; i++)
                {
                    temperature = i;
                    if (temperature > 95)
                    {
                        MakeAlert(temperature);
                        ShowMsg(temperature);
                    }
                }
            }
            // 发出语音警报
            private void MakeAlert(int param)
            {
                Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:", param);
            }
            // 显示水温
            private void ShowMsg(int param)
            {
                Console.WriteLine("Display:水快开了,当前温度:{0}度。", param);
            }
        }
        class Program
        {
            static void Main()
            {
                Heater ht = new Heater();
                ht.BoilWater();
                Console.ReadLine();
            }
        }
    }
    
    3.4.3 实现示例的Observer设计模式
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace TestEventAndDelegate
    {
        // 热水器
        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);
            }
        }
        class Program
        {
            static void Main()
            {
                Heater heater = new Heater();
                Alarm alarm = new Alarm();
                heater.BoilEvent += alarm.MakeAlert; //注册方法
                heater.BoilEvent += (new Alarm()).MakeAlert; //为匿名对象注册方法
                heater.BoilEvent += Display.ShowMsg; //注册静态方法
                heater.BoilWater();//烧水,会自动调用注册过对象的方法
                Console.ReadLine();
            }
        }
    }
    

    3.5 委托进阶

    相关文章

      网友评论

        本文标题:第一部分:C#语言基础----委托和事件

        本文链接:https://www.haomeiwen.com/subject/glxqmxtx.html