.net----委托和事件

news2024/12/23 6:18:26

委托和事件

  • 委托
    • 声明
    • 实例化
    • 调用
    • 将类型安全的函数指针(方法)作为其他方法的参数进行传递,从而实现函数回调方法
    • 委托:匿名方法委托
  • 多播委托
    • 委托:委托的异步调用
    • 委托:委托的兼容性
  • 事件
    • 事件实际上是委托的一种特殊形式,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派生

  • 声明事件处理委托

  • 声明引发事件的类

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

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

  • 声明处理事件的类

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/32384.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软考-系统架构师-计算机与网络基础知识-数据库系统基础知识

文章目录1.关系数据库基础1.1关系型数据库基础1.1.1数据库的结构与模式1.1.2实体联系E-R模型1.1.3数据的规范化1.1.4事务管理1.1.5并发控制1.1.6数据库的备份和恢复2.关系数据库设计2.1数据库设计的特点2.2数据库的设计方法2.3数据库设计的基本步骤3.分布式数据库系统3.1分布式…

simulink中比scope模块还好用的平替出图工具?

今天在捣拾scope模块比较几个数据大小,拉坐标线非常的不方便,而且对于调参时几组数据的比较非常繁琐,这里介绍以下simulink中自带的数据检查器(Data Inspector),个人认为比scope模块方便查看出图结果,有帮助的童鞋们赶…

算法设计与分析 SCAU11090 最大m段乘积和最小m段和(优先做)

11090 最大m段乘积和最小m段和(优先做) 时间限制:1000MS 代码长度限制:10KB 提交次数:0 通过次数:0 题型: 编程题 语言: G;GCC;VC;JAVA Description 一个n位十进制整数S,若将S划分为m个段,则可以得到m个整数。 (1)这m个整数的…

有限元在游乐设施中的应用-焊缝计算

作者 | 九峰知己千杯少 一、前言 游乐设施金属结构所采用的连接方式有焊接连接、铆钉连接、普通螺栓连接和高强螺栓连接4种,将两块分离的金属其接头部分局部加热到熔化或半熔化状态,采取施加压力或不加压,或填充其他金属,利用原…

C#上位机系列(4)—示波器一新窗口的建立

本文是讲解C#.net平台的Winform框架下的第四个内容,手把手介绍上位机项目的创建方式以及一些写软件时常用的功能,讲解从零开始的每一个步骤。 本次介绍上位机中新窗口的建立方式和软件示波器的代码原理。 从此节开始,所有代码附后 1.新窗口…

element-plus中menu的基本知识点

在vue后台管理系统中,menu是经常会用到的必不可少的导航组件,这个组件如果是单纯的去使用,很简单。但是在实际开发过程中,与其有关的路由相结合使用,还是容易搞混一些东邪,所以想在这里记录一下。 从产品的…

SuperMap 云原生常见问题解决办法-consul启动异常

在iManager for K8S产品中,如果创建了云套件站点,会有三个consul的服务,consul在云套件中充当的角色是服务发现,服务注册,以及配置共享。如果consul服务失效,云套件的整体服务将不能正常运行。客户在使用云…

用DIV+CSS技术设计的环保主题网站(web前端网页制作课作业)

🎀 精彩专栏推荐👇🏻👇🏻👇🏻 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业…

教你如何在优麒麟上搭建 RISC-V 交叉编译环境

由于 RISC-V 设备价格昂贵、不易采购等诸多原因,许多小伙伴虽然很感兴趣,但仍无法参与 RISC-V 开发工作,今天就教大家如何在优麒麟上搭建 RISC-V 交叉编译环境,快学起来吧! 交叉编译(Cross Compile&#x…

收藏 | 机器学习公共数据集集锦(附下载链接)

>>>深度学习Tricks&#xff0c;第一时间送达<<< &#x1f680;&#x1f680;&#x1f680;近期&#xff0c;小海带在空闲之余&#xff0c;收集整理了一批机器学习公共数据集供大家参考。 整理不易&#xff0c;小伙伴们记得一键三连喔&#xff01;&#xff0…

cpu天梯图2022年11月 cpu排行榜天梯图2022

一、i9-13900K 1、13900K参数&#xff1a;24核32线程&#xff0c;睿频5.8GHz&#xff0c;基础功耗125W&#xff0c;最大睿频功耗253W。 2、推荐搭配主板&#xff1a;Z790、B760、Z690、B660。 3、目前单核性能最强的一款CPU&#xff0c;拥有超强的超频能力&#xff0c;为玩家带…

swift指针内存管理-引用

引用探究 首先看一个例子 那么这个 0x0000000000000003 是什么意思呢 回到swift源码 找到关键核心类型 HeapObject 就是 swift 分配内存获取到的结构类型 HeapObject 第一个8字节为 metadata, 接下来是宏 InlineRefCounts 其实 就是泛型真正类型 InlineRefCountBits 至此&am…

Android性能优化方法论

作为一名开发&#xff0c;性能优化是永远绕不过去的话题&#xff0c;在日常的开发中&#xff0c;我们可肯定都会接触过。Android 的性能优化其实是非常成熟的了&#xff0c;成熟的套路&#xff0c;成熟的方法论&#xff0c;成熟的开源框架等等。 对于接触性能优化经验较少的开…

大学生简单个人静态HTML网页设计作品 DIV布局个人介绍网页模板代码 DW学生个人网站制作成品下载

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

APS计划排程结果的量化评价

APS计划排程系统是供应链管理软件中的一种提升管理决策协助系统软件&#xff0c;它通过约束理论、运用多种多样数学分析优化计算方法、有常驻运行内存运转的互动式计算机软件。它借助于某些繁杂的数学运算方式 来处理多种多样自变量&#xff0c;使供应链管理的提升变成事实。 A…

计硕3班-陈陇刚-2022222278-第二章 递归与分治策略 作业

目录 1. 概括第二章学习内容&#xff0c;总结第二章学习心得 1.1 递归 1.1.1 递归的定义 1.1.2 递归的使用场景 1.2 分治 1.2.1 分治的定义 1.2.2 分治法使用场景 1.3 学习心得 2. 描述Fibonacci数列递归算法&#xff0c;并进行时间复杂度分析 2.1 Fibonacci数列定义 …

测试人经验谈:需求不明确也能写出测试用例

测试人员的用例编写&#xff0c;一般基于经验和需求文档进行&#xff0c;但是很多时候项目是没有需求的&#xff0c;特别是领导的某个概念提出&#xff0c;然后开发会根据自己的理解完成&#xff0c;测试人员在没有获得任何依据和需求的情况下如何编写测试用例呢&#xff1f; …

【数据结构】七种排序方法,一篇文章掌握

文章目录前言1. 直接插入排序1.1 画图演示1.2 直接插入排序详细步骤1.3 时间复杂度&#xff0c;空间复杂度分析2. 希尔排序2.1 具体步骤描述2.2 代码详解2.3时间复杂度,空间复杂度分析3. 选择排序3.1 画图讲解3.2 代码讲解3.3 时间复杂度,空间复杂度分析4. 快速排序4.1 画图演示…

【C++初阶7-string】真方便,真舒服

前言 本期浅学一下STL的stirng。 内容概览&#xff1a; STLstring 是什么为什么怎么用&#xff08;接口介绍及使用&#xff09; 博主水平有限&#xff0c;不足之处望请斧正&#xff01; 先导 STL C中非常重要的一个东西&#xff0c;STL(Standard Template Library) 标准…

详解华夏银行iDo平台一体化运维的落地过程

随着数字化转型的深入&#xff0c;基于中台和PaaS架构的一体化运维建设也在各行各业快速展开&#xff0c;但是如何将运维平台本身的能力与企业已有的工具能力进行中台化整合、工具场景如何联动&#xff0c;是个复杂而庞大的工程。 本次&#xff0c;史春志老师以华夏银行运维平…