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

第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();
        }
第一部分:C#语言基础----委托和事件_第1张图片

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


第一部分:C#语言基础----委托和事件_第2张图片

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


第一部分:C#语言基础----委托和事件_第3张图片

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

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");
        }
第一部分:C#语言基础----委托和事件_第4张图片
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#语言基础----委托和事件)