当前位置: 首页 > article >正文

浅谈C#事件

一、基本介绍

        事件是一种特殊的多播委托,用于实现发布-订阅模式。事件允许对象在发生特定情况时通知其他对象。事件的发布者(也称为事件源)定义事件,并在适当的时机触发事件;事件的订阅者(也称为事件处理程序)订阅事件,并在事件被触发时接收通知。

事件的基本使用

定义事件:在类中定义一个事件,通常使用 event 关键字。

public class Publisher
{
    // 定义一个事件
    public event EventHandler MyEvent;

    // 触发事件的方法
    protected virtual void OnMyEvent(EventArgs e)
    {
        MyEvent?.Invoke(this, e);
    }

    // 调用该方法来触发事件
    public void DoSomething()
    {
        // 执行某些操作...
        OnMyEvent(EventArgs.Empty);
    }
}

订阅事件:在另一个类中订阅事件。

public class Subscriber
{
    public void Subscribe(Publisher publisher)
    {
        publisher.MyEvent += OnPublisherEvent;
    }

    private void OnPublisherEvent(object sender, EventArgs e)
    {
        Console.WriteLine("Publisher raised an event!");
    }
}

取消订阅事件:如果不再需要接收事件通知,可以取消订阅。

public void Unsubscribe(Publisher publisher)
{
    publisher.MyEvent -= OnPublisherEvent;
}

事件的触发

事件本身不是方法,而是一种特殊的多播委托。在类内部,通常会有一个受保护的方法来触发事件,这个方法会调用事件委托。使用 ?. 操作符可以确保在事件没有订阅者时不会引发空引用异常。

事件的安全性

  • 线程安全:在多线程环境中,事件的触发应该考虑线程安全。可以使用 lock 语句来同步对事件委托的访问。
  • 避免空引用异常:使用 ?.Invoke 来避免在没有订阅者时引发空引用异常。

事件的高级特性

  • 自定义事件参数:可以定义自定义的事件参数类来传递更复杂的数据。
  • 弱事件模式:为了减少内存泄漏的风险,可以使用弱事件模式。在这种模式下,事件订阅者持有事件源的弱引用。

示例:使用自定义事件参数

public class Publisher
{
    public event EventHandler<MyEventArgs> MyEvent;

    protected virtual void OnMyEvent(MyEventArgs e)
    {
        MyEvent?.Invoke(this, e);
    }

    public void DoSomething(string message)
    {
        OnMyEvent(new MyEventArgs { Message = message });
    }
}

public class MyEventArgs : EventArgs
{
    public string Message { get; set; }
}

public class Subscriber
{
    public void Subscribe(Publisher publisher)
    {
        publisher.MyEvent += OnPublisherEvent;
    }

    private void OnPublisherEvent(object sender, MyEventArgs e)
    {
        Console.WriteLine($"Publisher raised an event with message: {e.Message}");
    }
}

在这个示例中,MyEventArgs 是一个自定义的事件参数类,它允许事件处理程序接收额外的信息。事件的发布者在触发事件时创建并传递这个自定义事件参数的实例。


http://www.kler.cn/a/290520.html

相关文章:

  • OSS文件上传
  • 统信UOS开发环境支持Electron
  • 天地图入门|标注|移动飞行|缩放,商用地图替换
  • Python 实现阿里滑块全攻略
  • 大模型预训练+微调大模型;大模型提示/指令模式”(Prompt/Instruct Mode)
  • Flutter 主流常用第三方库、插件收集
  • 在 Facebook 上投放广告需要多少钱?
  • Docker续6:容器网络
  • CentOS 部署 RocketMQ 详细指南
  • Multi-Mode DOA Estimation AND Relax Super Resolution DOA
  • C# 窗口页面布局
  • 深入探究 RocketMQ:分布式消息中间件的卓越之选》
  • 有没有性价比高一些的开放式耳机推荐?盘点四款高性价比蓝牙耳机
  • 智能代码编辑器:Visual Studio Code的深度剖析
  • C++:Opencv读取ONNX模型,通俗易懂
  • jmeter响应断言、json断言、断言持续时间、大小断言操作
  • 暴力破解和撞库攻击有什么区别,怎么防御暴力破解和撞库攻击
  • FPGA进阶教程16 同一块FPGA的两个网口实现arp自通信
  • Opencv中的直方图(4)局部直方图均衡技术函数createCLAHE()的使用
  • windows修改升级时间
  • 九、安装artifactory并配置PostgreSQL--失败了
  • 如何通过本地服务器来测试环信的回调功能
  • powershell自动提交git脚本
  • Android 13 aosp 恢复出厂设置流程
  • 快消品渠道开发方案,让你拥有源源不断的批发客户!
  • 2.门锁_STM32_舵机设备实现