C#事件的用法

前言

在C#中,事件(Event)可以实现当类内部发生某些特定的事情时,它可以通知其他类或对象。事件是基于委托(Delegate)的,委托是一种类型安全的函数指针,它定义了方法的类型,使得可以将方法作为参数进行传递。

事件包含以下一些基本概念:

委托(Delegate):定义了一个方法的类型,使得可以将方法作为参数传递。

事件(Event):基于委托的,用于在类或对象之间提供通知的机制。

事件处理器(Event Handler):是一个符合特定签名的方法,用于响应事件。

1、如何定义事件

定义事件

首先,你需要定义一个委托,然后基于这个委托来声明一个事件。

下面这个委托MyEventHandler有两个参数,第一个参数是object类型,第二个参数是TempEventArgs类型,TempEventArgs这个类型是我自己定义的,继承于EventArgs。

csharp 复制代码
 public delegate void MyEventHandler(object sender, TempEventArgs e);//声明一个委托
csharp 复制代码
public class TempEventArgs : EventArgs
    {
        public double Temp { get; set; }
        public TempEventArgs(double temp)
        {
            this.Temp = temp;
        }
    }

然后定义一个包含事件的类如下:

csharp 复制代码
  //定义一个类,这个类包含一个事件,这个类也称为目标类
        class Thermostat
        {
            //声明事件
            public event MyEventHandler MyEventHandlerEvent = delegate { };//空委托,这样我们就不用在调用事件时先进行null值判断了。

            private double _CurrentTemperature;
            public double CurrentTemperature
            {
                get
                {
                    return _CurrentTemperature;
                }
                set
                {
                    if (value != CurrentTemperature)
                    {
                        _CurrentTemperature = value;
                        MyEventHandlerEvent?.Invoke(this, new TempEventArgs(CurrentTemperature));//触发事件
                    }
                }
            }
        }

上面的Thermostat类中定义了一个MyEventHandlerEvent事件,事件由event修饰,基于MyEventHandler这个委托类型。并且通过属性CurrentTemperature的值的改变来触发事件,事件触发时其实就是调用委托,并且给委托传递了两个参数,第一个参数是Thermostat对象,第二个参数是将改变后的温度传入TempEventArgs类型的对象。

2、订阅和取消订阅事件

其他类或对象可以通过+=操作符来订阅事件,通过-=操作符来取消订阅事件,比如Cooler这个类就是一个需要订阅事件的其他类,这个类包含了一个事件处理器TemperatureChanged,当订阅事件以后,当事件触发以后,就会根据事件做出相应的处理。

复制代码
 /// <summary>
    /// 这个类称为观察者类
    /// </summary>
    class Cooler
    {
        public Cooler(double temperature)
        {
            this.Temperature = temperature;

        }
        public double Temperature { get; set; }//温度阈值

        //事件处理器
        public void TemperatureChanged(object sender, TempEventArgs tempEventArgs)
        {
            double temperature = tempEventArgs.Temp;
            if (temperature > Temperature)
            {
                Console.WriteLine("当前温度过高,冷却器开启");
            }
            else
            {
                Console.WriteLine("当前温度过低,冷却器关闭");
            }
        }
    }

下面的代码通过 +=为cooler对象订阅事件,订阅事件以后,通过 thermostat.CurrentTemperature = 60;这行代码可以触发事件。当使用-=取消订阅事件以后,通过thermostat.CurrentTemperature = 50;也不能触发事件了。

csharp 复制代码
Thermostat thermostat = new Thermostat();
            Cooler cooler = new Cooler(50);
            thermostat.MyEventHandlerEvent += cooler.TemperatureChanged;//为目标增加观察者,也叫做为cooler对象订阅事件
            thermostat.CurrentTemperature = 60;

            thermostat.MyEventHandlerEvent -= cooler.TemperatureChanged;//为目标减去观察者,也叫做为cooler对象取消订阅事件
            thermostat.CurrentTemperature = 50;
相关推荐
叫我阿柒啊3 分钟前
Java全栈开发面试实战:从基础到微服务的深度解析
java·jvm·微服务·vue3·springboot·全栈开发·restfulapi
cxyxiaokui00112 分钟前
检索增强生成(RAG):打破模型知识壁垒的革命性架构
java·aigc
Monly2118 分钟前
Docker:部署Java后端
java·docker·容器
是店小二呀30 分钟前
【C++】智能指针底层原理:引用计数与资源管理机制
android·java·c++
tianyuanwo38 分钟前
技术总结:AArch64架构下Jenkins Agent(RPM容器编译节点)掉线问题分析与排查
java·linux·jenkins
weixin_4565881543 分钟前
【java面试day19】mysql-优化
java·mysql·面试
华仔啊2 小时前
别再问了!Java里这几种场景,用抽象类就对了
java·后端
掘金安东尼2 小时前
Rspack 推出 Rslint:一个用 Go 编写的 TypeScript-First Linter
前端·javascript·github
明天过后01222 小时前
PDF文件中的相邻页面合并成一页,例如将第1页和第2页合并,第3页和第4页合并
java·python·pdf
tingting01192 小时前
Spring Boot 外部配置指定不生效的原因与解决
java·spring boot·后端