c#事件、委托复习

99 阅读3分钟

一、委托

1.什么是委托

C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托(Delegate)  就是存有对某个方法的引用的一种引用类型变量,引用可在运行时被改变。

委托是C#中的一种引用类型,委托的本质是一个类,定义了方法的类型,是将方法作为参数传递到另一个方法的特殊类。 委托可以认为是持有一个或者多个方法的对象,当委托被调用时,它持有的方法也会被调用。 委托是方法的抽象,它存储的就是一系列具有相同签名和返回回类型的方法的地址。 委托不是对象,是一种类型

2.委托的应用

委托的使用遵循三步走的原则,即定义声明委托,实例化委托,调用委托。

3.使用委托

    //定义了一个委托,没有函数体,相对于定义了一个变量,这个变量可以赋值给其他函数
    delegate void Delegate1(int i);
        //定义一个静态方法来方便调用
    public static void test1(int num)
        {
            Console.WriteLine(num);
        }

调用委托,将函数名直接赋值给委托变量,后面直接调用对应的委托变量 注意:这时候调用的委托变量里面的实参值要跟方法里面的形参值是要一一对应的。

//声明了一个委托,d可以存函数的变量,存放的是test类型的函数,
            Delegate1 d = test1;
            d(10);

4.多播委托

多播委托是指在一个委托中注册多个方法,

            //在注册方法时可以在委托中使用加号运算符或者减号运算符来实现添加或撤销方法
            d += test1; 
            d -= test1; //通过减掉一个函数,去掉一个函数,在调用的时候就没有这个函数了
            d(18);
            

注意:d+=test1这时候会调用俩次的,d=d+test1,相对于d(18)的时候,首先调用d(18),其次test1(18)的方法 结果截图如下:

image.png

5.委托的另外一种调用方式

    d.Invoke(35);

实质上还是d(35)。

二、事件

1.事件是什么

事件的本质其实是对委托的封装,是委托的安全包裹,只能在类内部调用和赋值,让委托的使用更具有安全性

2.事件的使用

  • 声明事件 image.png
  • 事件和委托的区别 image.png
  • 事件总结 image.png

练习

有一个热水器类,里面申明了一个事件myEvent,委托的类型为无返回值,形参为小数(温度值),还有温度的初始值为0度,还有一个报警器类,有一个showInfo的方法会打印出当前温度为xx度,最后还有一个显示器类,也有一个showInfo方法,打印了当前水已烧开,热水器类中有一个加热的方法每隔200毫秒给給水加一度,当水到95度时显示器和报警器中的方法开始调用(使用事件调用)

    namespace 委托和事件的练习
{
    //声明一个热水器类
    public class HeatWaterQ
    {
        public event Action<double> myEvent;
        //初始温度值
        double temp = 0;
        //加热的方法
        public void heat()
        {
            Warning w = new Warning();
            screen s = new screen();
            while (temp<95)
            {
                Thread.Sleep(200);
                myEvent = s.showInfo;
                myEvent(temp);
                temp = temp + 1;
            }
            Console.WriteLine(temp);
            if (myEvent != null &&temp == 95.0)
            {
                myEvent = w.showInfo;
                myEvent(temp);
            }
        }

    }
    //声明一个报警类
    public class Warning
    {
        public void showInfo(double temp)
        {
            Console.WriteLine($"当前水已经烧开,温度为{temp}度");
        }
    }
    //声明一个显示器类
    public class screen
    {
        public void showInfo(double temp)
        {
            Console.WriteLine("正常烧水,当前温度为{0}度", temp);
        }
    }
    internal class Program
    {

        static void Main(string[] args)
        {
            HeatWaterQ h = new HeatWaterQ();
            h.heat();
            //调用的结果也可以在类中使用也可以在外部类通过添加和删除来改变和调用
        }
    }
}