C#中的委托与事件实例详解

C#中的委托(Delegate)和事件 (Event)详解与使用范例 阅读详情

本人博客中的代码都是本地测试通过,意思和注释理解了就行

本篇文章引用张子阳博客基本思路,然后根据自己的经验,进行了部分的简化和修改,委托就在于理解,多看几遍就理解了。

委托:本质上讲委托是一种可以将方法作为参数的方法,可以包含参数也可以不包含参数

事件:从本质上将也是委托,只不过是进行了封装的委托。事件可以绑定方法,绑定之后就会监视这些方法,当达到事件的触发条件,就会执行事件绑定的方法

如果比较绕口的话请读10遍就理解了

分五个步骤:

1.委托将方法作为参数传递:将方法作为参数进行传递,当某一个方法作为参数传递时,一起传递的还有这个方法对应的参数

举例:

class Program
{
    //定义委托
    public delegate void GreetDelegate();
    private static void EnglishGreeting(string name)
    {
        Console.WriteLine("Morning,"+name);
    }
    private static void ChaineseGreeting(string name)
    {
        Console.WriteLine("早上好,"+name);
    }
    //定义一个接收GreetingDelegate类型的方法
    private static void GreetPeople(string name,GreetDelegate MakeGreeting)
    {
        MakeGreeting(name);
    }
    
    static void Main(string[] args)
    {
        //将方法作为参数传递,并同时传递方法执行需要的参数
        GreetPeople("cdc",EnglishGreeting);
        GreetPeople("奇点码农",ChineseGreeting);
        Console.ReadKey();
    }
}

2.委托可以通过+=绑定方法,也可以通过-=消除委托对方法的绑定

//将方法绑定到委托
class Program
{
    public delegate void GreetDelegateHandler(string name);
    public static void EnglishGreeting(string name)
    {
        Console.WriteLine("Morning,"+name);
    }
    private static void ChineseGreeting(string name)
    {
        Console.WriteLine("早上好,"+name);
    }

    static void Main(string[] args)
    {
        GreetDelegateHandler delegate1;
        //将方法绑定到委托
        delegate1=EnglishGreeting;
        delegate1+=ChineseGreeting;
        delegate1("cdc");
    }
}

3.事件出马:事件类似于进行了封装的委托类型的变量,事件的参数与与之对应的委托的参数一致

class Program
{
    public delegate void GreetDelegateHandler(string name);
    
    private static void EnglishGreeting(string name)
    {
        Console.WriteLine("Morning,"+name);
    }

    private static void ChineseGreeting(string name)
    {
        Console.WriteLine("早上好,"+name);
    }
    
    public class GreetManager
    {
        public event GreetDelegateHandler GreetDelegate;
        
        public void GreetPeople(string name)
        {
            //事件的参数与与之对应的委托的参数一致
            GreetDelegate(name);
        }
    }

    static void Main(string[] args)
    {
        GreetManager gm=new GreetManager();    
        gm.GreetDelegate+=EnglishGreeting;
        gm.GreetDelegate+=ChineseGreeting;
        gm.GreetPeople("cdc");
        Console.ReadKey();
    }
}

4.Observer设计模式

(1)Subject:被监视对象,包含着其他对象感兴趣的内容

(2)Observer:监视者,监视Subject,当Subject中的某事件发生的时候,会告知Observer,而Observer则会采取相应行动

//注:Observer设计模式是为了定义对象的一种一对多的依赖关系,以便当一个对象的状态改变时,其他依赖于它的对象会自动告知并更新执行

//被监视对象
public class Heater
{
    private int temperature;
    //声明委托
    public delegate void BoilHandler(int param);
    //使用委托声明事件
    public event BoilHandler BoilEvent;
    //烧水
    public void BoilWater()
    {
        for(int i=0;i<=100;i++)
        {
            Thread.Sleep(500);
            temperature=i;
            if(temperature>95)
            {
                if(BoilEvent!=null)
                {
                    BoilEvent(temperature);
                }
            }
        }
    }
}
//监视者:警报器
public class Alarm
{
    public void MakeAlert(int param)
    {
        Console.WriteLine("Alarm:滴滴。。。,水已经{0}度了",param);
    }
}
//监视者:显示器
public class Display
{
    public static void ShowMsg(int param)
    {
        Console.WriteLine("Display:水快烧开了,当前温度:{0}度",param);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Heater heater=new Heater();
        Alarm alarm=new Alarm();
        //注册方法
        heater.BoilEvent+=alarm.MakeAlert;
        //给匿名对象注册方法
        heater.BoilEvent+=(new Alarm()).MakeAlert;
        //注册静态方法
        heater.BoilEvent+=Display.ShowMsg;
        //调用被监视对象执行方法,每当被监视对象的方法中触发一次事件,就会将该事件绑定的所有监视者方法执行一遍
        heater.BoilWater();
        Console.ReadKey();
    }
}

5.委托类型的代码规范

(1)委托类型的名称都应该以Event Handler结束

(2)委托的原型定义有一个void返回值,并接收两个输入参数:一个Object类型,一个EventArgs类型(或者继承自EventArgs)

(3)事件的命名为委托去掉EventHandler之后的剩余部分

(4)继承自EventArgs的类型应该以EventArgs结尾

//热水器
public class Heater
{
    private int temperature;
    //添加型号作为演示
    public string type="RealFire001";
    //添加产地作为演示
    public string area="China Xian";
    //声明委托
    public delegate void BoiledEventHandler(object sender,BoiledEventArgs e);
    //声明事件
    public event BoiledEventHandler Boiled;
    //定义BoiledEventArgs类,传递给Observer所感兴趣的信息
    public class BoiledEventArgs:EventArgs
    {
        public readonly int temperature;
        public BoiledEventArgs(int temperature)
        {
            this.temperature=temperature;
        }
    }
    
    //可以供继承自Heater类的重写,以便继承类拒绝其他对象对它的监视
    protected virtual void OnBoiled(BoiledEventArgs e)
    {
        //如果该事件已经注册方法,则触发对应的方法
        if(Boiled!=null)
        {
            //调用所有注册对象的方法
            Boiled(this,e);
        }
    }
    //烧水
    public void BoilWater()
    {
        for(int i=90;i<=100;i++)
        {
            Thread.Sleep(500);
            temperature=i;
            if(temperature>95)
            {
                //建立Boiled的EventArgs对象
                BoiledEventArgs e=new BoiledEventArgs(temperature);
                OnBoiled(e);
            }
        }   
    }
}

//监视器:警报器
public class Alarm
{
    public void MakeAlert(object sender,Heater.BoiledEventArgs e)
    {
        Heater heater=(Heater)sender;
        //访问sender中的公共字段
        Console.WriteLine("Alarm:{0}-{1}:",heater.area,heater.type);
        Console.WriteLine("Alarm:滴滴,水温{0}度!",e.temperature);
        Console.WriteLine();
    }
}
//监视器:显示器
public class Display
{
    public static void ShowMsg(object sender,Heater.BoiledEventArgs e)
    {
        Heater heater=(Heater)sender;
        Console.WriteLine("Display:{0}-{1}:",heater.area,heater.type);
        Console.WriteLine("Display:显示水温{0}度。",e.temperature);
        Console.WriteLine();
    }
}

class Program
{
    static void Main(string[] args)
    {
        Heater heater=new Heater();
        Alarm alarm=new Alarm();
        //注册方法
        heater.Boiled+=alarm.MakeAlert;
        //给匿名对象注册方法
        heater.Boiled+=(new Alarm()).MakeAlert;
        //注册方法
        heater.Boiled+=new Heater.BoiledEventHandler(alarm.MakeAlert);
        //注册静态方法
        heater.Boiled+=Display.ShowMsg;
        //调用烧水的方法,会自动调用注册的方法
        heater.BoilWater();
        Console.ReadKey();
    }
}

 

第六节、C# 上位机委托 & 事件详解(异步通信与 UI 更新实战版 委托(Delegate)是 C# 中的类型安全的方法指针,本质是 “方法模板的定义”—— 它规定了方法的返回值类型、参数列表格式,任何符合该格式的方法都可以被委托引用,实现 “通过委托间接调用方法”,无需直接依赖方法所属类。解耦:通信层(如串口类)无需知道 UI 层的具体更新方法,只需通过委托调用,实现两层分离;灵活:一个委托可以引用多个方法(多播委托),实现 “一处触发,多处响应”(如串口接收数据后,同时更新 UI、存储数据库、触发报警);异步支撑:配合异步操作(如Task。 阅读详情

相关推荐

C#中的委托和事件

C#中有个委托和事件 从“delegate”关键字开始,因为这是你在使用委托时会使用的主要方法。 编译器在你使用 delegate 关键字时生成的代码会映射到调用 Delegate 和 MulticastDelegate 类的成员的方法调用。 可使用类似于定义方法签名的语法来定义委托类型。 只需向定义添加 delegate 关键字即可。 具体应用实例如下: using System; using ...

道亦无名 1万+

C#委托和事件的使用实例

使用委托时要先实例化,和类一样,使用new关键字产生委托的新实例,然后将一个或者多个与委托签名匹配的方法与委托实例关联。随后调用委托时,就会调用所有与委托实例关联的方法。 与委托关联可以是任何类或者结构中的方法,可以是静态方法,只要是可以访问的方法都可以。 1.创建一个委托类型使用关键字delegate(委托) public delegate void DelegateChangeStart(string str);//创建一个实例 public class Program { #region 定义

chinaherolts2008的博客 1055

C#中委托、事件及异步编程实例详解

委托(Delegate)在C#中是一种引用类型,它能够引用一个具有特定参数列表和返回类型的方法。可以想象委托是一个“容器”,它持有方法的引用,并且能够在运行时被赋予不同的方法。委托主要用于实现回调函数和事件处理机制,它支持将方法作为参数传递给其他方法。多播委托是C#语言中委托(Delegate)的一个扩展,它能够在委托对象上调用多个方法。它本质上是一个封装了方法的列表,在调用多播委托时,实际上是在调用这个列表中的每一个方法。

weixin_31597759的博客 824

C#中委托和事件

关于委托和事件分享三个博客内容: 首先说明下: (1)C#中事件:事件时属于类的成员,所以要放在类的内部。 (2)委托属于一个定义,是和类、接口类似的,通常放在外部。 (因为大多数委托都要被重用) 委托定义在类里面还是类外面视情况而定,一般定义在与类定义平级部分, 且用public修饰,便于外部调用。 若定义在类的内部,则必须通过调用该类的成员才能取得其委托的引用, 频繁...

andu1644的博客 1万+

C#编写的委托与事件的十个精典的例子(可以直接运行)

C#编写的委托与事件的十个精典的例子(可以直接运行)C#编写的委托与事件的十个精典的例子(可以直接运行)C#编写的委托与事件的十个精典的例子(可以直接运行)

C#委托与事件(张子阳).pdf

委托与事件,举例描述了委托与事件,非常易懂,值得一看!强烈推荐

C#泛型委托事件详解及实例

// 泛型委托的构造类型:需要一个形参为int类型、返回值类型为bool类型的方法对其进行初始化/// 泛型委托的构造类型:需要一个形参为string类型、返回值类型为int类型的方法对齐进行初始化.NET给我们预定义了很多泛型委托,日常编码工作中使用这些类型的泛型委托基本就已足够,下面我们只介绍三个常用的预定义的泛型委托。

u011555996的博客 1350

C# 委托事件简单的使用例子

这是C# 委托与事件简单的使用例子。 只是为了初学者更好的接受委托与事件使用方法而已。 程序有两个窗体,一个是主窗体,一个是副窗体。 打开主窗体,在主窗体中点按钮后,打开副窗体,在副窗体中,可以调整主窗体的透明度。 代码中有详细解释。有不明白,我们可以继续交流。

C# 中的委托和事件(详解,附实例)

C# 中的委托和事件 1引言 委托和事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。本文中,我将通过两个范例由浅入深地讲述什么是委托、为什么要使用委托、事件的由来。.Net Framework中的委托和事件、委托和事件对Observer设计模式的意义,对它们的中间代码也做了讨论。 2将方法作为方法的参数 首先来看看下面

彼岸花 1470

C#委托事件-张子阳.pdf

这本资料给我们提供了一个很好的例子,水浒烧水的案例,相信会对大家有用,所以就贡献出来于大家分享!

RTL8211F千兆PHY原理图与PCB设计:从手册到量产的完整指南

在工业网关、边缘计算和FPGA/CPU以太网扩展设计中,千兆PHY芯片的稳定运行取决于外围电路的精细设计。RTL8211F(I)作为应用广泛的物理层收发器,其原理图设计涉及电源域划分、时钟与复位时序、RGMII/ MDIO接口匹配以及MDI差分网络等多个环节。正确理解数据手册的阅读顺序,掌握100Ω差分阻抗控制、等长约束和EMI布局技巧,是保证链路可靠性和信号完整性的关键。本文从芯片选型与数据手册解析切入,系统梳理从电源去耦到PCB布局布线的工程实践要点,帮助工程师规避Link不稳定、MDIO读取失败、吞吐

weixin_28721917的博客 349

Python.NET事件与委托详解:让Python函数接管C回调与事件订阅

**Python.NET** 是连接 Python 与 .NET 运行时的桥梁。本指南聚焦它最实用的两大特性:**委托(Delegate)** 与 **事件(Event)**——让普通的 Python 函数直接接管 C# 的回调与事件订阅,用一行 `+=` 就能把事件处理逻辑交给 Python,几乎零样板代码。 ## 一、委托与事件:30 秒理解核心概念 如果你熟悉 Python 的函数式风格

gitblog_01161的博客 805

OrangePi Kunpeng Pro 安装 ROS2 + Gazebo

OrangePi Kunpeng Pro 的优点很明显,内置openEuler,配备PD电源,做到开箱即用;板子设计也不错,风扇噪音不大,散热良好,昇腾芯片又确保小板子的性能,接口丰富是这类板子共同的优点,也很好的继承了下来,甚至还可以外接固态,可靠性大大提升。使用起来,哪怕不用openEuler的话,也可以很方便的刷Ubuntu来实现一些需要依赖的开发工作,这次没有跑AI模型,所以对算力的优势还没有很明显的感受,下次可以试一下yolo跑跑看。

Arcan 1824

如何在 C# 中使用 委托

委托是一个类型安全的函数指针,它可以引用与委托具有相同签名的方法,你可以利用 委托 实现事件或者回调函数,多播委托 可以引用一个或者多个具有相同签名的方法。 理解 委托 本质上来说,委托包含了一个对方法的引用,概念上和 C ++ 上的函数指针是一样的,唯一不一样的是 C# 中的 委托 是类型安全的,你可以将方法作为参数传给 委托,而从让 委托 持有对方法的引用,委托常用于定义成 回调函数 和 事件处理,一般用 delegate 关键词去声明,可以将 delegate 定义成 类平级,也可以嵌套在 类中。 使

一线码农的专栏 380

MATPOWER的安装详细教程

MATPOWER的安装包实际为一个程序包,安装教程很简单,详见本文。

半个月亮Zz的博客 3万+

人工智能训练师认证教程(5)使用MONAI进行医学影像分析的完整指南

本文介绍了使用MONAI框架进行医学影像分析的全流程。首先详细说明了环境搭建步骤,包括PyTorch和MONAI的安装配置。然后以肺部CT 3D分割为例,分步骤讲解了数据准备与预处理、3D UNet模型构建、训练配置(DiceLoss损失函数、Adam优化器等)以及训练验证循环的实现。文章还包含推理可视化方法和模型导出为ONNX格式的部署方案,并强调了医学影像分析中的数据格式适配、强度归一化、显存优化等关键注意事项。最后指出MONAI的医学专用组件可大幅简化开发流程,建议后续可探索SwinUNETR等进阶方

华为开发者布道师,天府英才计划,致力于大数据+AI 的应用创新,助力企业与个人AI创新赋能。 1208

C#委托与事件_附实例

C#委托和事件 事件的由来 委托也是—种类型,根据面向对象编程的特性,通常会把—个类型的变量封装到类的内部,并把其设置成private的,然后通过属性来访问该变量。 所以在实际编程时委托类型也会定义 在类里面使用event关键字来修饰委托变量。 其本质上是委托变量的属性. 理解事件 1.事件提供了更好的封装性,还能起到限制作用。 2.事件的订阅和退阅,是通过“+=”和“-=”操作来实现的。 事件实例1: public delegate void Greeting(string name); public

一名Unity工程师的养成方法 2150

Unity新手必看:5分钟搞定TextMeshPro中文乱码,告别小方块(附7000+常用字库)

本文详细介绍了Unity中TextMeshPro中文乱码问题的解决方案,包括快速生成中文字体的步骤和优化技巧。通过使用支持中文的.ttf字体文件和自定义字符集,开发者可以在5分钟内解决TMP显示小方块的问题,提升游戏或应用的文本显示效果。

weixin_33095355的博客 362

c#事件委托示例

事件编程的基本要素,C#事件编程通常包含以下三个核心步骤:定义委托,声明事件,触发事件

日月清心 357

cartographer从入门到精通(一):cartographer介绍

Cartographer的架构图我们可以看到白色框出来的三个区域,分别是Input Sensor Data(数据输入模块)Local SLAM(局部SLAM模块)Global SLAM (background thread)(全局SLAM模块)下面我们分别介绍一下这几个模块。

weixin_68094467的博客 1052

RT-DETR算法优化改进:轻量级上采样CARAFE算子 | 注意力机制大作战

上采样操作CARAFE,具有感受野大、内容感知、轻量级、计算速度快等优点,引入RT-DETR二次创新;1)代替Upsample进行使用;

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 1265

C# 实例解析事件委托之EventHandler

概述 事件属于委托的一个子集,像我们平时界面上的鼠标点击按钮后响应事件、事件的发布和订阅等都需要用到委托.通过委托可以很好的实现类之间的解耦好。事件委托EventHandler的函数原型如下:delegate 表示这个个委托,事件委托没有返回值,有两个入参,sender是事件触发的对象,e是一个泛型的事件类型参数public delegate void EventHandler<TE...

dotNET跨平台 832

淘宝母婴用品数据挖掘及可视化分析研究

1. 背景介绍 在当今的电子商务时代,母婴用品市场已经成为了各大电商平台的一片蓝海。淘宝作为中国最大的电子商务平台,其上的母婴用品交易数据自然引人关注。理解这些数据,可以帮助商家更好地制定营销策略,也可以帮助消费者更好地选择产品。因此,本文将对淘宝母婴用品的数据进行深入的挖掘和分析。 1.1 电子商务的

AI天才研究院 1257

C#中的事件和委托那些事

概要 我们在做C#的WinForm,WPF或Web Form开发时候,总是要与事件和委托打交道。可能大家会有这些疑问,到底什么是事件,什么是委托,事件和委托是什么关系,事件模型又是什么,为什么C#的事件语法糖会引起歧义,委托是不是可以替代事件。本文希望能通过一个收短信拿快递的例子,帮助大家理清事件和委托的这些事。 基本定义 事件与委托的定义 按照MS的定义如下: 事件:Events enable a class or object to notify other classes or objects whe

weixin_43263355的博客 496

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

【Unity基于C#事件委托机制,最轻松易懂的版本,一个实例解决你的困惑】

PS:题主涉世尚浅,如有不对的地方还请大佬指出~对于C#的委托和事件机制,看似复杂抽象,但其逻辑条理十分清晰,所以理解起来也不会太难,关键在于了解它两的联系,以及工作原理。委托观察者模式: 定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。 什么是委托: C#语言通过委托来实现回调函数的机制,而回调函数是一种很有用的编程机制,可以被广泛的用在观察

_阿松先生的博客 605

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

C#委托以及在事件驱动编程中的使用

在C#中,委托是一个类,它能够存储对方法的引用。委托的定义类似于一个方法的原型,它指定了方法的返回类型和参数列表。例如:这个委托可以用来引用任何返回类型为void,且接受一个string参数的方法。首先,定义一个委托,用于指定事件处理方法的签名。委托的签名应该与事件处理方法的签名相匹配。例如:在类中定义一个事件,该事件将触发委托所引用的方法。通常,事件使用event关键字声明。例如:实现事件处理方法,其签名必须与委托所指定的签名匹配。当事件触发时,这些方法将被调用。

最后一个bug的博客 723

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

上一篇: 读取图片的方法
下一篇: Task用法详解
奇点码农
博客等级 码龄19年 60粉丝 140原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值