探寻C#事件本质

2023-05-16

我最先在学习C#事件的时候,阅读了许多书籍,但总是不能对事件建立起一个比较清晰的概念,对其内部机制和原理也是似是而非,因为这些书籍在描述事件的时候总是夹杂许多其他不能理解的抽象术语,相信许多初学者都有这样的感觉。

同时,在利用IDE进行GUI编程时,IDE总是在内部帮助我们实现了事件必须的一些代码,我们只需双击对象,编事件处理函数就行了,而我们常常对内部的工作一无所知,或没有去主动理解这些自动生成的代码。

现在我试着回答学习时遇到的几个问题,这将会有助于你理解到底什么是事件。

如何定义一个事件?

语法:修饰符 event关键字 委托类名 事件名;

比如:public event somedelegatename myeventname;

事件到底是什么类型(引用?值?)

事件其实就是一个特殊的委托。

MSDN中的C#参考里这样描述:事件是特殊类型的多路广播委托,仅可从声明它们的类或结构(发行者类)中调用。如果其他类或结构订阅了该事件,则当发行者类引发该事件时,会调用其事件处理程序方法。

对于这一点,我们也可以从事件的定义中看出,不过就是在定义委托对象时加了event关键字表明这个委托现在叫事件。

何谓事件的订阅(subscribe)?

我们用VS2005建立一个只有一个按钮的winform程序,双击按钮,设计器会在Form1.Designer.cs中自动生成一行代码

 this.button1.Click += new System.EventHandler(this.button1_Click);

这就是事件的订阅!其实就是用事件处理函数this.button1_Click来实例化一个委托System.EventHandler(这个函数与委托拥有同样的签名,为什么需要有同样签名,我理解就是要保证委托与函数的类型一致,这样才能把函数句柄赋给一个委托对象,即所谓的用委托封装方法或C++中把一个方法句柄赋给一个函数指针),并把这个委托对象赋给事件Click(因这Click其实就是一个委托引用,所以可以这样做,从C++的角度来理解,就是把事件处理函数赋给了一个函数指针变量,这样就可以通过调用这个函数指针以执行事件处理函数)

一句话,订阅事件就是将某个委托对象指向一个具体的方法。

什么是引发事件?

当程序中满足某个条件时调用事件就是引发了事件,为什么可以调用事件呢?因为事件就是一个委托,而委托具有C++中函数指针的作用,调用委托就是调用委托中封装的事件处理函数

为什么事件可以被多个对象订阅?

知道了事件实际是一个多播委托后,这个问题不难理解,所谓被多个对象订阅,就是事件被触发后,可以导致多个对象做出反应,也就是多个对象的某个事件处理函数被调用。为什么会这样呢,因为事件是多播委托,即封装了多个函数的委托,调用这个委托实际上就是在调用被封装的这多个函数。

 

下面用一个最简单的控制台程序例子来说明事件的运作方式

using System;
namespace  最简单的自定义事件
{
  
///   <summary>
  
///  事件发送类,即调用事件的类
  
///   </summary>
   class  Class1
  {
    
public   delegate   void  mydelegate( object  sender,EventArgs e);  // 定义委托
     public   event  mydelegate myevent;  // 定义一个委托类型的事件,即定义一个委托对象

    
public   void  run()
    {
      
// 死循环,不停测试某个条件是否满足,即所谓的监听
       while ( true )
      {
        
if (Console.ReadLine() == " a " )
        {
          myevent(
this , new  EventArgs());  // 调用事件
        }
      }
    }
  }

  
///   <summary>
  
///  事件接收类,即事件处理的类
  
///   </summary>
   class  Class2
  {
    
static   void  Main( string [] args)
    {
      Class1 c1 
=   new  Class1();
      c1.myevent
+=   new  Class1.mydelegate(c1_myevent);  // 将委托对象指向具体的事件处理函数,即所谓的订阅事件
      c1.run(); // 运行这个事件,因为此时委托已经指向了具体方法,可以运行了
    }

    
private   static   void  c1_myevent( object  sender, EventArgs e)
    {
// 事件处理方法
      Console.WriteLine( " 你触发了事件! " );
    }
  }
}

 对于这个例子,为了加深理解事件的本质,我们可以把事件订阅c1.myevent+= new Class1.mydelegate(c1_myevent); 这句注释掉,即事件没有指向任何具体的方法,编译,不会报错,运行它,如果我们不输入字符串“a”,程序仍然运行正常,因为这时没有满足事件触发条件,一旦输入a回车,就会报如下错误:

未处理的异常:System.NullReferenceException未将对象引用设置到对象实例。

很显然,就是相当于我们调用了一个没有指向任何函数的函数指针。

这是我学习事件的一点心得,特别欢迎大家批评指正,因为知道错了不可怕,可怕的是不知道自己错了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

探寻C#事件本质 的相关文章

  • Security ❀ CSP Bypass 内容安全策略绕过

    文章目录 内容安全策略绕过 CSP Bypass1 Low Level2 Medium Level3 High Level4 Impossible Level 内容安全策略绕过 CSP Bypass CSP 内容安全策略 xff1a 为了缓
  • Security ❀ JavaScript Attacks 前端攻击

    文章目录 JavaScript Attacks 前端攻击1 Low Level2 Medium Level3 High Level4 Impossible Level JavaScript Attacks 前端攻击 JavaScript是一
  • MiddleWare ❀ Zookeeper基础概述

    文章目录 1 认识Zookeeper1 1 数据类型1 2 监听器1 3 基本功能1 3 1 统一配置管理1 3 2 统一命名服务1 3 3 分布式锁1 3 4 集群状态 2 下载安装包3 安装服务3 1 服务端命令3 2 客户端命令 3
  • Java文件内容变更及内容追加监听方案

    简介 对于文件内容变动的监听处理 xff0c 一般分为两种主要应用场景 1 只关心文件内容是否发生变更 文件的内容发生变动的场景是全量修改模式 xff0c 不是内容追加模式 例如某xml文件内容发生变动 这种情况 xff0c 我们一般只需要
  • MiddleWare ❀ MySQL基础概述

    文章目录 MySQL基础1 SQL语法与分类1 1 DDL 数据定义语言1 1 1 库操作1 1 1 1 查询1 1 1 2 创建1 1 1 3 删除1 1 1 4 使用 1 1 2 表 43 字段操作1 1 2 1 查询1 1 2 2 创
  • Shell ❀ 基础知识概述

    文章目录 一 基本概念1 脚本文件命名方式2 解释器分类3 基本基本组成内容4 脚本编写规范与格式说明5 自动生成脚本的注释与配置信息 一 基本概念 shell又称为命令解释器 xff0c 它能识别用户输入的各种命令 xff0c 并传递给操
  • Shell ❀ 基础变量类别与引用

    文章目录 二 变量与引用1 变量命名2 变量类型3 变量定义4 常用变量4 1 内置通配符4 2 内置变量4 3 自定义变量4 4 环境变量4 5 变量的作用域4 5 1 全局变量4 5 2 局部变量 4 6 位置变量4 5 1 位置变量的
  • Shell ❀ 条件测试语句

    文章目录 三 条件测试1 基本语法2 表达式2 1 条件判断表达式2 2 字符串判断表达式2 3 数字判断表达式2 4 文件判断表达式2 5 表达式中 与 的区别2 5 1 的逻辑判断表达式2 5 2 的逻辑判断表达式 三 条件测试 1 基
  • Shell ❀ 条件判断语句

    文章目录 四 条件判断1 if 单分支格式1 1 语法格式1 2 操作案例 2 if else 双分支格式2 1 语法格式2 2 操作案例 3 if elif else 多分支结构3 1 语法格式3 2 操作案例 4 和 复合指令4 1 相
  • Shell ❀ 循环语句

    文章目录 五 循环语句1 for 循环1 1 带列表的for循环1 2 不带列表的for循环1 3 类C风格的for循环 2 while 循环2 1 循环体读取文件的三种方法2 2 循环类型 3 嵌套循环案例 五 循环语句 1 for 循环
  • Shell ❀ 函数与数组

    文章目录 六 函数与数组1 函数1 1 函数定义1 2 函数的优势1 3 函数语法1 4 函数调用1 5 操作案例1 6 函数库文件1 7 递归函数 2 数组2 1 数组定义2 2 定义股关联数组2 3 数组的赋值2 4 数组操作2 5 数
  • Shell ❀ 正则表达式

    文章目录 七 正则表达式1 普通字符2 非打印字符3 特殊字符4 限定字符5 常用的正则表达式5 1 校验数字的表达式5 2 校验字符的表达式5 3 特殊需求表达式 七 正则表达式 正则表达式 Regular Expression xff1
  • Shell ❀ 三剑客 - Grep + Sed + Awk

    文章目录 八 三剑客 Grep 43 Sed 43 Awk1 Grep 过滤1 1 常用grep参数1 2 使用方法 2 Sed 行匹配2 1 执行原理2 2 常见语法2 3 使用方法2 3 1 地址边界的设定2 3 2 基础编辑命令2 3
  • Shell ❀ 学习笔记与知识点梳理

    基础知识概述基础变量类别与引用条件测试语句条件判断语句循环语句函数与数组正则表达式三剑客 Grep 43 Sed 43 Awk
  • 使用 Schema xsd 文件校验 xml 文件格式

    本文是实例代码工具类 xff1a span class token keyword import span span class token namespace org span class token punctuation span x
  • Linux 查看磁盘分区、文件系统、使用情况的命令和相关工具介绍

    nbsp Linux 查看磁盘分区 文件系统 使用情况的命令和相关工具介绍 提要 Linux 磁盘分区表 文件系统的查看 统计的工具很多 有些工具是多功
  • MiddleWare ❀ Elasticsearch请求详解

    文章目录 Elasticsearch请求详解 Elasticsearch请求详解 span class token comment 创建索引 重复创建报错 span span class token function curl span s
  • 树莓派自带VNC黑屏(灰屏)个人解决办法

    最近购买了树莓派 xff14 xff22 看来许多教程 xff0c 但VNC第一次还正常显示 xff0c 后来就黑屏 xff0c 还有什么现在不能显示桌面什么的 xff0c 下面给大家说下vnc黑屏我的解决办法 xff0c 我发现是vncv

随机推荐

  • Openmv色块追踪

    Openmv 拿到后第一次进行开发 xff08 颜色追踪 xff09 Openmv本身是具有很多的内置函数的 xff0c 基本都是别人给我们写好了 xff0c 需要我们自己去调用 xff0c 并给函数传递参数以实现我们需要的效果 但是很多初
  • XTDrone中roslaunch px4 indoor1.launch

    logging to home luyu ros log f8336262 666f 11ec ad21 4287fcc6d992 roslaunch luyu Lenovo 32405 log Checking log directory
  • Git的基本使用方法(0基础小白也能看懂)详细教程(含视频讲解)

    git指令介绍 xff0c 下面有详解指令可以先跳过直接看下面的详解 mkdir learngit 创建一个learngit文件夹 cd learngit 进入learngit文件夹 pwd 用于显示当前目录 git init 把这个目录变
  • 2020/05/25 Prometheus监控k8s企业级应用 1

    2 2 课程介绍及课程大纲 普罗米修斯的配置很难 2 3 Prometheus监控软件概述 prometheus是一名google的前员工写的 xff0c 也是go语言写的 xff0c K8S是第一个托管的项目 xff0c promethe
  • 现代信号处理——自适应滤波器(卡尔曼滤波)

    一 Kalman滤波的过程方程和观测方程 假设某系统n时刻的状态变量为x n 过程方程 xff1a x n 43 1 61 F n 43 1 xff0c n x n 43 v1 n 观测方程 xff1a y n 61 C n x n 43
  • 联想SR590服务器管理界面配置

    1 连接登录远程管理界面 将笔记本和服务器的管理口用网线连接 xff0c 配置笔记本的ip地址 xff0c 改成192 168 70 XXX xff0c 255 255 255 0 xff0c 如下图 xff1a 改完ip地址ping一下服
  • Qt鼠标点击不响应QMouseEvent事件的解决办法

    最近在写程序在和同事合完代码后发现一个问题 项目是使用qt开发一个程序 有一个功能是要实现地图的标记功能 我需要在一个label控件上显示地图 然后再选中标记按钮后点击地图 会在鼠标点击的位置放置一个标记的图标并储存备注信息 那么实现这个功
  • 匿名飞控程序整理

    主程序框图如下 xff0c 接下来我会将各个模块全部单独整理出来 xff0c 一是分享 xff0c 也是给自己留个便于查阅 主函数main c int main void flag start ok 61 All Init 进行所有设备的初
  • ORB_SLAM2 运行TUM RGBD数据集过程记录

    一 编译代码 这里是用ubuntu20 04 opencv4安装orbslam2的一点记录 报错信息经过搜索找到了对应的解决办法 xff0c 在这里做一个笔记 报错1 xff1a FATAL ERROR 34 OpenCV gt 2 4 3
  • 匿名飞控设备初始化All_Init()函数代码整理

    目录 初始化All Init 1 Para Data Init 参数初始化 2 Remote Control Init 遥控器输入类型 3 PWM Out Init 电调输出的初始化 4 spi 2初始化 xff0c 用于读取飞控板上所有传
  • 匿名飞控线程初始化和调度是怎么实现的

    目录 一 线程初始化 先看下Scheduler Setup xff08 xff09 函数 xff0c 二 任务调度器 函数在文件Ano Scheduler c中 xff0c Scheduler Setup xff08 xff09 初始化后
  • QGC编译报错error C2220: 警告被视为错误 最佳解决方法

    前面搜了一下 xff0c 试过各种方法依然报错 xff0c 先整理别人的解决方法 目录 一 重新保存文件 二 xff0c 更改编码方式 三 最终解决方案 xff1a 修改配置文件 一 重新保存文件 注意这里的配置 Wx WX 二 xff0c
  • 整理px4飞控校准机制和qgc校准机制

    用qgc执行 px4飞控传感器校准时 的步骤确实很麻烦 xff0c 磁罗盘需要转6个面 xff0c 加速度计也需要6个面 大疆无人机的校准很简单 xff0c 加速度计需要静置一会 xff0c 磁罗盘校准也就转一个面就行了 xff0c 就算学
  • mavros操作飞机时方向位置改为机体坐标系下指令

    前面试了很多 xff0c 看官网里的说明 用 mavros setpoint raw local 34 里的frame id改为 34 base link 34 不行 又直接发mavros msgs PositionTarget 修改里面的
  • px4室内飞行通过SLAM发送位置消息

    先按照官方的教程设置好飞控参数 http docs px4 io master zh computer vision visual inertial odometry html 下载源码学习 xff1a https github com A
  • MCUXpresso调试FreeRTOS时显示多线程

    多线程程序调试起来确实麻烦 xff0c 在调试过程中默认只能看到当前线程 按照以下配置即可在程序暂停时查看多线程的状态 xff1a 在debug配置中选中下图所示 xff1a 配置完成后再调试程序即可显示多线程
  • px4 编译生成msg消息机制及将其移植方法

    目录 一 在px4中添加新的Topic 二 px4生成msg生成的结构体优势 三 msg生成工具及移植方法 一 在px4中添加新的Topic 在px4中是通过uorb进行消息的传递 xff0c 通过根目录下的msg文件可以添加自定义的消息
  • px4传感器数据sensor模块整理

    涉及传感器数据的流程 xff0c 大致整理如下图 传感器的数据从drivers中调用lib中dirvers对应的对象更新数据并发布出去 xff0c sensor模块通过订阅原始数据和校准参数 xff0c 对数据滤波并更正 xff0c 然后再
  • C#实现程序一次打开两个窗口,两个窗口分别放置在两个屏幕

    这是本人在编程中碰到的一个问题 xff0c 寻找了其他案例 xff0c 都只是同时打开两窗口 xff0c 但不能实现在拥有两块显示屏时候 xff0c 分别将两个不同的窗口显示在两个单独的屏幕 源代码https download csdn n
  • 探寻C#事件本质

    我最先在学习C 事件的时候 xff0c 阅读了许多书籍 xff0c 但总是不能对事件建立起一个比较清晰的概念 xff0c 对其内部机制和原理也是似是而非 xff0c 因为这些书籍在描述事件的时候总是夹杂许多其他不能理解的抽象术语 xff0c