.net----委托和事件

2023-05-16

委托和事件

  • 委托
    • 声明
    • 实例化
    • 调用
    • 将类型安全的函数指针(方法)作为其他方法的参数进行传递,从而实现函数回调方法
    • 委托:匿名方法委托
  • 多播委托
    • 委托:委托的异步调用
    • 委托:委托的兼容性
  • 事件
    • 事件实际上是委托的一种特殊形式,C#使用一种委托模型来实现事件
    • 事件的声明、订阅和取消
    • 事件:实现的步骤

委托

  • 委托是C#用来处理需用函数指针来处理的情况的

  • 委托是完全面向对象的(同时封装了对象实例和方法),是类型安全的

  • 委托可保存对方法的引用的类,但只能对于其签名匹配的方法进行引用

  • 委托声明定义一个从 System.Delegate 类派生的类

  • 委托实例封装了一个调用列表,该列表列出了一个或多个方法,每个方法称为一个可调用实体

  • 对于实例方法,可调用实体由该方法和一个相关联的实例组成

声明

[委托修饰符] delegate 返回值类型 委托名 ([形参列表]);

实例化

委托名 委托实例名 = new 委托名(匹配方法);

调用

委托实例名(实参列表);

将类型安全的函数指针(方法)作为其他方法的参数进行传递,从而实现函数回调方法

 delegate void D(int x);       // 声明委托
    class C
    {
        public static void M1(int i){Console.WriteLine("C.M1:" + i);}
        public static void M2(int i){Console.WriteLine("C.M2:" + i);}
        public void M3(int i){Console.WriteLine("C.M3:" + i);}
    }
    
class Test
    {
        static void Main()
        {
            D d1 = new D(C.M1);  //使用new关键字,创建委托对象,指向类静态方法
            d1(-1);              //调用M1
            D d2 = C.M2;        //使用赋值运算符,创建委托对象,指向类静态方法
            d2(-2);             //调用M2
            C objc = new C();
            D d3 = new D(objc.M3); //使用new关键字,创建委托对象,指向对象实例方法
            d2(-3);              //调用M3
            Console.ReadKey();
        }
    }

委托:匿名方法委托

  • 无需先声明类或结构以及与委托匹配的方法,而是在创建委托的实例时,直接声明与委托匹配的方法的代码块(匿名方法)
delegate void Printer(string s); //声明委托
class TestClass
{  
      static void Main()
      {  // 使用匿名方法实例化delegate类
         Printer p = delegate(string j)
         { Console.WriteLine(j); };
         p("使用匿名方法的委托的调用。"); 
         //匿名delegate调用结果
         Console.ReadKey();
      }
  }     

多播委托

委托也可以包含多个方法,这种委托称为多播委托

  • 调用多播委托实例,则按顺序依次调用多播委托实例封装的调用列表中的多个方法
  • 声明多播委托时,其返回类型必须为void
  • 三个静态方法:Combine, Remove, RemoveAll
  • 多播委托通过 + 或 += 向多播委托实例封装的调用列表中添加方法;通过 – 或 – = 从多播委托实例封装的调用列表中删除方法
delegate void D(int x);
    class C
    {
        public static void M1(int i) { Console.WriteLine("C.M1: " + i);} 
        public static void M2(int i) { Console.WriteLine("C.M2: " + i);}
    }
    class Test
    {
        static void Main()
        {  D cd1 = new D(C.M1);  cd1(-1); //调用 M1
           D cd2 = new D(C.M2);  cd2(-2); //调用M2
           D cd3 = cd1 + cd2; 	cd3(10);   //先调用M1,然后调用M2
           cd3 -= cd1;  cd3(20); //删除M1,调用M2
           cd3 -= cd2;        //删除M2后,调用列表为null
           // cd3(70);         //抛出System.NullReferenceException异常
           cd3 -= cd1;        //没有M1可删除,但不报错
           Console.ReadKey();
        }
    }

委托:委托的异步调用

在这里插入图片描述

委托:委托的兼容性

  • 与委托向对应的方法不必与委托签名完全匹配

  • 方法M与委托类型D兼容条件:

  • D和M的参数数目相同,且各自对应参数具有相同的ref或out修饰符

  • 对于每个ref或out参数,D中的参数类型与M中的参数类型相同

  • 存在从M的返回类型到D的返回类型的标识或隐式引用转换。即允许方法具有的派生返回类型比委托中定义的更多(协变)

  • 每一个值参数(没有 ref 或 out 修饰符的参数)都存在从D中的参数类型到M中的对应参数类型的标识或隐式引用转换。允许方法具有的派生参数类型比委托类型中的更少(逆变)

事件

处理机制;事件的声明、订阅和取消;.NET Framework事件模型

  • 一种使对象或类能够提供通知的成员

  • 类或对象可以通过事件向其他类或对象通知发生的相关事情

  • 发送(或引发)事件的类称为“发行者”(生产者),接收(或处理)事件的类称为“订户”(消费者)

  • 事件是对象发送的消息,以发信号通知操作的发生

  • 在 .NET Framework 类库中,事件是基于 EventHandler 委托和 EventArgs 基类的

事件实际上是委托的一种特殊形式,C#使用一种委托模型来实现事件

  • 事件模型分为事件生产者和事件消费者,其处理机制大致可以分为下列4步:

  • 在事件生产者类中声明一个事件成员,即某种事件处理委托(简称为事件委托)的实例(多播事件委托实例);

  • 在事件消费者类中声明与事件委托相匹配的事件处理方法;

  • 通过“+=”向多播事件委托实例封装的调用列表中添加事件处理方法,或通过“-=”从多播事件委托实例封装的调用列表中删除事件处理方法;

  • 在事件生产者类中添加有关发生事件的代码,即当满足某种条件时(发生事件),则调用委托,即调用多播事件委托实例封装的调用列表中添加的事件处理方法。如果没有订阅,即事件实例为Null,则不作任何处理
    在这里插入图片描述

button.Click += new EventHandler(this.Button_Click);//按钮单击事件

private void Button_Click(object sender, EventArgs e) // 声明按钮单击事件处理方法
{
      box.BackColor = System.Drawing.Color.Green;  // 文本框背景色改为绿色
}

事件的声明、订阅和取消

  • 声明
    [修饰符] event 事件委托名 事件名;
    事件委托名(sender, e)

  • 订阅和取消
    对象.事件名 +=委托实例;
    对象.事件名 -=委托实例;

 //声明事件处理委托
    public delegate void SampleEventHandler(object sender, EventArgs e);
    public class Publisher 
    {
        public event SampleEventHandler SampleEvent; //声明事件
        protected virtual void RaiseSampleEvent()     //产生事件
        {  //若不需要传递消息参数,可直接使用EventArgs对象
            SampleEvent(this, new EventArgs());    //引发事件
        }
    }
public class Subscriber
    {
        public static void Method1(object sender, EventArgs e)
        {
            Console.WriteLine("To Do Something...");
        }
        public static void Method2(object sender, EventArgs e)
        {
            Console.WriteLine("To Do Something...");
        }
}
public static void Main()
{  / /创建委托实例
            SampleEventHandler d1 = new SampleEventHandler(Subscriber.Method1);
            Publisher p = new Publisher(); 
//订阅事件
            p.SampleEvent += d1;
            p.SampleEvent += new SampleEventHandler(Subscriber.Method2);
//订阅事件
            p.SampleEvent -= d1;       //取消事件
            Console.ReadKey();
        }

事件:实现的步骤

  • 声明提供事件数据的类,从System.EventArgs派生

  • 声明事件处理委托

  • 声明引发事件的类

  • 在事件生产类中,声明事件

  • 在事件生产类中,实现产生事件的代码

  • 声明处理事件的类

  • 在事件消费类中,声明事件处理方法

  • 在事件消费类中,订阅或取消事件

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

.net----委托和事件 的相关文章

  • 第八届蓝桥杯客观题答案

    解析 2 OC门又叫集电极开路门 5 地线也算信号线 6 RS232 不能调试下载吧 xff1f JATG 4线 xff08 不用VCC xff09 SWJ 5线 SPI 不是下载线 xff0c 通信用的 xff0c 而且也有五根 7 答案
  • Python学习笔记:Pyqt5鼠标键盘事件处理

    import sys from PyQt5 QtCore import from PyQt5 QtGui import from PyQt5 QtWidgets import class windows QMainWindow def in
  • c++成员函数后面加一个冒号:

    冒号后跟着的是赋值操作 xff0c 这种写法是c 43 43 的特性 比如 xff0c LRUcache int capacity cap capacity 相当于 LRUcache int capacity cap 61 capacity
  • python---布谷鸟搜索算法

    布谷鸟搜索算法 xff08 Cuckoo Search xff0c CS xff09 布谷鸟算法的启发当然来自于布谷鸟 xff0c 因为布谷鸟这种鸟很有意思 xff0c 生出来的孩子自己不养 xff0c 直接被扔到其他鸟的鸟巢中去了 xff
  • THRESH_OTSU mode: > ‘src_type == CV_8UC1 || src_type == CV_16UC1‘ > where > ‘src_type‘ is 6

    问题 xff1a python cv2 报错 xff1a 原因 OTSU算法是由日本学者OTSU于1979年提出的一种对图像进行二值化的高效算法 xff0c 是一种自适应的阈值确定的方法 xff0c 又称大津阈值分割法 xff0c 是最小二
  • 树莓派4B安装ubuntu mate崩溃(卡死)解决办法

    初次安装过程中 不要连WIFI xff01 xff01 xff01 不要接网线 xff01 xff01 xff01 我重装了不下15次所得来的惨痛教训 xff01 xff01 xff01
  • ubuntu20.04配置FrankMocap实现3D人体姿态估计

    一 初始环境配置 1 ubuntu20 04配置显卡驱动 以我的这篇文章为例子 xff0c 显卡RTX2060及以下的都可以使用我的方法快速完成配置 xff0c RTX2060以上的我尚未进行尝试 xff0c 请自行斟酌尝试 联想拯救者R7
  • 使用VNC远程控制树莓派的Ubuntu20.04(arm)

    一 将PC与树莓派连接到同一个局域网内 比如 xff1a 将树莓派和PC连接到同一个wifi中 xff0c 方法一 xff1a 如果是家用wife发射器 xff0c 则可以在浏览器中输入 xff1a http 192 168 0 1 来查询
  • vue笔记

    ES6相关补充 var 没有块级作用域 let 有块级作用域 ES5之前因为if和for都没有块级作用域的概念 xff0c 只能借助function的作用域来解决应用外面变量的问题 let有if和for的块级作用域 变量作用域 xff1a
  • python3字符串

    Python3 字符串 字符串是 Python 中最常用的数据类型 我们可以使用引号 或 来创建字符串 创建字符串很简单 xff0c 只要为变量分配一个值即可 例如 xff1a var1 61 Hello World var2 61 Run
  • html思维导图

    标题标签 标题标签 h1 h5 xff0c 字体从大到小 对应英文语义headline 使用注意 xff1a 标题里的文字要xian想水平居中或者垂直居中得用text align和line height来做 xff0c 内外边距不行 xff
  • 什么是MVVM?

    什么是MVVM MVVM是Model View ViewModel的缩写 MVVM是一种设计思想 View层是视图层 xff0c 也就是用户界面 前端主要由HTML和CSS来构建 xff1b Model层 是指数据模型 xff0c 泛指后端
  • Docker——Windows版本Docker安装

    目录 一 简介 1 1 Docker如何解决大型项目依赖关系复杂 xff0c 不同组件依赖的兼容性问题 xff1f 1 2 Docker如何解决开发 测试 生产环境有差异的问题 1 3 Docker 和 虚拟机的区别 1 4 Docker架
  • 细说C++中的 :: 和 : 的区别

    C 43 43 中的 1 类的作用域 作用域符号 的前面一般是类名称 xff0c 后面一般是该类的成员名称 xff0c C 43 43 为例避免不同的类有名称相同的成员而采用作用域的方式进行区分 假如 xff1a A B表示两个类 xff0
  • 扰动观测器(DOB)设计

    snf 机器人机械手可能会受到不同类型的干扰 例如未知的有效载荷 未建模的动力学和环境相互作用力 观察机器人操纵器中的这些未知干扰是许多机器人应用的基础 例如干扰抑制和无传感器力控制 机械手在进行正常操作时可能会受到不同类型的干扰 粗略地说
  • Gazebo安装教程——在 Ubuntu 上安装Gazebo的源代码

    安装工具 建议使用一些额外的工具来帮助编译源代码 xff0c 尽管其他正确获取和构建源代码的方法也是可能的 获取所有库的源代码的最简单方法是使用 vcstool 要以正确的顺序编译所有不同的库和 ign gazebo xff0c 建议使用c
  • 线性与非线性控制

    控制理论领域可以分为两个分支 xff1a 线性控制理论 这适用于由遵循叠加原理的设备组成的系统 xff0c 这大致意味着输出与输入成正比 它们由线性微分方程控制 一个主要的子类是另外具有不随时间变化的参数的系统 xff0c 称为线性时不变
  • 模型预测控制(Model predictive control,MPC)

    模型预测控制 MPC 是一种先进的过程控制方法 xff0c 用于在满足一组约束条件的同时控制过程 自 1980 年代以来 xff0c 它一直在化工厂和炼油厂的加工工业中使用 近年来 xff0c 它还被用于电力系统平衡模型 1 和电力电子学中
  • 蓝桥杯单片机官方测试程序现象

    IO模式 xff0c 矩阵按键下 xff1a 开机次数 测试AT24C02 S7 测试LED 按2次 S11 测试DAC 按4次 S15 测试ADC双通道 按2次 S19 测试超声波 S6 测试温度模块 S10 0 测量 S14 测试继电器
  • 51单片机的1T和12T的区别

    1T 模式 不分频 1个系统基本时钟 xff0c 执行一个动作 xff1b 12T模式 12分频 12个系统基本时钟 xff0c 执行一个动作 xff1b 因此 xff0c 12T模式和1T模式执行相同次数的动作 xff0c 12T模式需要

随机推荐

  • python2数据类型

    Python3 数字 Number Python 数字数据类型用于存储数值 数据类型是不允许改变的 这就意味着如果改变数字数据类型得值 xff0c 将重新分配内存空间 以下实例在变量赋值时 Number 对象将被创建 xff1a var1
  • keil中的extern的使用

    C51头文件使用extern的目的是外部变量或函数声明 使用时要注意 1 extern最好写在 h文件中 xff0c 方便后期的可读性 2 在使用extern进行外部变量声明时 xff0c 不能重新给变量赋值 例如 xff1a extern
  • STC89C52RC/RD中定时器2的使用方法

    学过一段时间单片机的你发现 xff0c 中断服务函数可以在主函数进行的同时 xff0c 进行一些对时间要求高的模块的配置时 xff0c 则要用到定时器中断 而如果你要实现多个功能的操作 xff0c 会使用多个定时器是必要的STC89C51单
  • keilC51中调试的方法(主要介绍串口调试XCOM)

    在keilC51中调试的方法的方法有很多 xff1a 1 直接看现象 2 串口调试 3 debug调试 下面终点讲串口调试 xff1a 若要实现printf重定向 重写printf调用的putchar函数 xff0c 重定向到串口输出 需要
  • data/xdata/pdata/code

    dada最大在128byte xff0c 不然就会报错 data xdada最大在512byte xff0c 不然就会报错 xdata pdata stc89c52中未使用 code xff08 将ROM内的定值存在程序存储器中 xff0c
  • 基于PID算法(python)的飞控设计学习日志(一)

    PID算法基础 首先我们需要去了解PID算法的数学原理 xff0c 数学原理部分借鉴于 64 确定有穷自动 机 的博客 一文读懂PID控制算法 xff08 抛弃公式 xff0c 从原理上真正理解PID控制 xff09 总的来说 xff0c
  • JAVA- 浅谈==与equal()的区别

    目录 gt 基础 gt 基本数据类型 gt 引用数据类型 gt Java内存 gt 区别 61 61 和equals gt 61 61 gt equals gt 总结 gt 基础 要想区分这两者 xff0c 我们得先明白什么是基本数据类型和
  • Ubuntu20.04+RealSense D455

    Ubuntu20 04装RealSense D455的驱动 Ubuntu20 04装RealSense D455的驱动 官网链接和个人链接 官网链接和个人链接 前言 xff1a 这些是我ubuntu20 04安装时候所找到的方法 xff0c
  • 【Java开发】 Mybatis-Plus 04:条件构造器-wrapper

    条件构造器算是Mybatis Plus中很重要的知识点了 xff0c 个人觉得它类似于Service的链式查询 xff0c 将诸多条件集中在一个wrapper中 xff0c 以达到高效便捷的目的 本文也是对01 02 03 内容的整合归纳
  • PrusaSlicer2.5中文说明1(新手篇)

    下载PrusaSlicer 稳定版本 PrusaSlicer的最新稳定版本始终可以在DRIVERS amp APPS包中找到 xff0c 它适用于Windows Mac OS X和Linux 该软件包还包括测试对象和打印机驱动程序 xff0
  • ROS机器人开发学习记录2——通过opencv读入本地图像并显示

    使用opencv和ros实现彩色图的读入和显示 为了实现该功能 xff0c 我使用了以下主要函数 xff0c 先对这些函数的功能做简要记录 xff1a xff08 1 xff09 Mat obj 61 imread 本地图像路径 实例 F
  • python中函数的参数分类

    python中函数的参数 形参 xff1a 定义函数时代表函数的形式参数 实参 xff1a 调用函数时传入的实际参数 列如 xff1a def f x y x y形参 print x y f 1 2 1 2 实参 定义函数时 xff0c 形
  • 信号量(sem)控制访问有限共享资源的线程数

    信号量 sem t就是个资源计数器 xff0c 用于控制访问有限共享资源的线程数 span class token macro property span class token directive keyword include span
  • 不需要各种代码的MATLAB语法高亮的设置,简单实用

    文章目录 前言一 代码高亮是什么 xff1f 二 设置步骤1 点击主页再点击预设2 点击MATLAB再点击颜色别着急因为是窗口太小哦所以要放大取消使用系统颜色 xff0c 然后自己选择文本颜色和背景颜色 总结 前言 这次主要想说说MATLA
  • 优先级队列(堆)

    优先级队列 1 什么是优先级队列2 什么时候用它什么时候不用它3 它的具体用法记得import两个库 xff1a 3 1定义3 2输入输出 1 什么是优先级队列 优先级队列就是用库内已有的类 xff0c 这个类名字是队列 xff0c 其实不
  • 2.1 关系模型的基本概念

    文章目录 2 1 1 基本术语定义2 1 用二维表格表示实体集 xff0c 用关键码表示实体间联系的数据模型称为关系模型 xff08 relational Model xff09 在关系模型中 xff0c 关键码 key 简称键 由一个或多
  • 2.2 关系代数的五个基本操作

    文章目录 前言2 2 关系代数2 2 1 关系代数的五个基本操作 1 投影 xff08 Projection xff09 2 选择 xff08 Selection xff09 选择与投影组合 3 xff09 并 xff08 Union xf
  • web的一些介绍

    文章目录 前言一 什么是Web xff1f 二 基本Web服务结构软件编程体系C S xff08 Client Server xff09 软件体系结构B S xff08 Brower Server xff09 软件体系结构C S结构与B S
  • .net技术第一章

    文章目录 NETC C Sharp 的特点C 的应用范围 NET Framework1 2 创建简单的C 程序结构和书写规则类型的声明和使用类型的声明和使用命名空间使用方法命名空间举例 注释Main方法命令行参数Main返回值 控制台输入和
  • .net----委托和事件

    委托和事件 委托声明实例化调用将类型安全的函数指针 方法 作为其他方法的参数进行传递 xff0c 从而实现函数回调方法委托 xff1a 匿名方法委托 多播委托委托 xff1a 委托的异步调用委托 xff1a 委托的兼容性 事件事件实际上是委