C#中的delegate 与event(一)

从语言进化角度理解c#(委托篇) c#1 是在2002年初的时候发布的,目前开发语言有很多,我个人还是觉得c++,java,c#算是老大哥级别,天下游戏一大抄,其实语言也是一样。虽然每个语言的设计者都不一样,但大家的核心思想还是比较接近的(大家都是互相抄的) 那么在c#1时代,最具代表性的几个语言特点是什么呢。我觉得有下面几个: 1:委托 2:属于c#的类型系统 3: 4:元表与反射 5:接口 6:值与引用,两种类型所涉及的托管与非托管机制 不急不急,那我们来一个个聊, 先来聊聊第一个。委托是什么东西: ... 阅读详情
在基于Windows平台的程序设计中,事件(event)是一个很重要的概念。因为在几乎所有的Windows应用程序中,都会涉及大量的异步调用,比如响应点击按钮、处理Windows系统消息等,这些异步调用都需要通过事件的方式来完成。即使在下一代开发平台——.NET中也不例外。

那么什么是事件呢?所谓事件,就是由某个对象发出的消息,这个消息标志着某个特定的行为发生了,或者某个特定的条件成立了。比如用户点击了鼠标、socket上有数据到达等。那个触发(raise)事件的对象称为事件的发送者(event sender),捕获并响应事件的对象称为事件的接收者(event receiver)。

在这里,我们将要讨论的是,在.NET的主流开发语言C#中如何使用自定义的事件来实现我们自己的异步调用。

在C#中,事件的实现依赖于delegate,因此我们有必要先了解一下delegate的概念。

Delegate

delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类。与其它的类不同,delegate类能够拥有一个签名(signature),并且它只能持有与它的签名相匹配的方法的引用。它所实现的功能与C/C++中的函数指针十分相似。它允许你传递一个类A的方法m给另一个类B的对象,使得类B的对象能够调用这个方法m。但与函数指针相比,delegate有许多函数指针不具备的优点。首先,函数指针只能指向静态函数,而delegate既可以引用静态函数,又可以引用非静态成员函数。在引用非静态成员函数时,delegate不但保存了对此函数入口指针的引用,而且还保存了调用此函数的类实例的引用。其次,与函数指针相比,delegate是面向对象、类型安全、可靠的受控(managed)对象。也就是说,runtime能够保证delegate指向一个有效的方法,你无须担心delegate会指向无效地址或者越界地址。

实现一个delegate是很简单的,通过以下3个步骤即可实现一个delegate:

1.  声明一个delegate对象,它应当与你想要传递的方法具有相同的参数和返回值类型。

2.  创建delegate对象,并将你想要传递的函数作为参数传入。

3.  在要实现异步调用的地方,通过上一步创建的对象来调用方法。

下面是一个简单的例子:

 

using System;

public class MyDelegateTest

{

        // 步骤1,声明delegate对象

        public delegate void MyDelegate(string name);

        // 这是我们欲传递的方法,它与MyDelegate具有相同的参数和返回值类型

        public static void MyDelegateFunc(string name)

        {

               Console.WriteLine("Hello, {0}", name);

        }

 

        public static void Main()

        {

               // 步骤2,创建delegate对象

               MyDelegate md = new MyDelegate(MyDelegateTest.MyDelegateFunc);

               // 步骤3,调用delegate

               md("sam1111");

        }

}

输出结果是:Hello, sam1111

了解了delegate,下面我们来看看,在C#中对事件是如何处理的。

在C#中处理事件

C#中的事件处理实际上是一种具有特殊签名的delegate,象下面这个样子:

public delegate void MyEventHandler(object sender, MyEventArgs e);

其中的两个参数,sender代表事件发送者,e是事件参数类。MyEventArgs类用来包含与事件相关的数据,所有的事件参数类都必须从System.EventArgs类派生。当然,如果你的事件不含参数,那么可以直接用System.EventArgs类作为参数。

就是这么简单,结合delegate的实现,我们可以将自定义事件的实现归结为以下几步:

1.           定义delegate对象类型,它有两个参数,第一个参数是事件发送者对象,第二个参数是事件参数类对象。

2.           定义事件参数类,此类应当从System.EventArgs类派生。如果事件不带参数,这一步可以省略。

3.           定义事件处理方法,它应当与delegate对象具有相同的参数和返回值类型。

4.           用event关键字定义事件对象,它同时也是一个delegate对象。

5.           用+=操作符添加事件到事件队列中(-=操作符能够将事件从队列中删除)。

6.           在需要触发事件的地方用调用delegate的方式写事件触发方法。一般来说,此方法应为protected访问限制,既不能以public方式调用,但可以被子类继承。名字是OnEventName。

7.           在适当的地方调用事件触发方法触发事件。

下面是一个简单的例子:

 

using System;

 

public class EventTest

{

        // 步骤1,定义delegate对象

     public delegate void MyEventHandler(object sender, System.EventArgs e);

     // 步骤2省略

public class MyEventCls

     {

// 步骤3,定义事件处理方法,它与delegate对象具有相同的参数和返回值类// 型

            public void MyEventFunc(object sender, System.EventArgs e)

            {

                   Console.WriteLine("My event is ok!");

            }

     }

     // 步骤4,用event关键字定义事件对象

     private event MyEventHandler myevent;

 

     private MyEventCls myecls;

 

     public EventTest()

     {

            myecls = new MyEventCls();

            // 步骤5,用+=操作符将事件添加到队列中

            this.myevent += new MyEventHandler(myecls.MyEventFunc);

     }

     // 步骤6,以调用delegate的方式写事件触发函数

     protected void OnMyEvent(System.EventArgs e)

     {

            if(myevent != null)

                   myevent(this, e);

     }

 

     public void RaiseEvent()

     {

            EventArgs e = new EventArgs();

            // 步骤7,触发事件

            OnMyEvent(e);

     }

 

     public static void Main()

     {

            EventTest et = new EventTest();

            Console.Write("Please input 'a':");

            string s = Console.ReadLine();

            if(s == "a")

            {

                   et.RaiseEvent();

            }

            else

            {

                   Console.WriteLine("Error");

            }

     }

}

 

输出结果如下,黑体为用户的输入:

Please input ‘a’: a

My event is ok!

小结

通过上面的讨论,我们大体上明白了delegate和event的概念,以及如何在C#中使用它们。我个人认为,delegate在C#中是一个相当重要的概念,合理运用的话,可以使一些相当复杂的问题变得很简单。有时我甚至觉得,delegate甚至能够有指针的效果,除了不能直接访问物理地址。而且事件也是完全基于delegate来实现的。由于能力有限,本文只是对delegate和event的应用作了一个浅显的讨论,并不深入,我希望本文能够起到抛砖引玉的作用。真正想要对这两个概念有更深入的了解的话,还是推荐大家看MSDN
C#性能优化黑科技(一)【反射】修改属性的快速方法 当我们在撸码的时候,不可避免的要使用反射来修改属性的值。我们都知道这种反射是太阳一般的慢,如果属性类型是值类型,那么就会因为装箱拆箱产生额外的GC(垃圾回收)。那么加快速度并减少GC呢,本文将介绍一个名为“CreateDelegate”的黑科技。 阅读详情

相关推荐

C#动态执行字符串(动态创建代码)的实例代码

在编写C#程序的时候,有时我们需要动态生成一些代码并执行。然而C#不像JavaScript有一个Eval函数,可以动态的执行代码。所有这些功能都要我们自己去完成

c#如何使用反射去创建一个委托_C# 反射的委托创建器

.Net 的反射是个很好很强大的东西,不过它的效率却实在是不给力。已经有很多人针对这个问题讨论过了,包括各种各样的 DynamicMethod 和各种各样的效率测试,不过总的来说解决方案就是利用 Expression Tree、Delegate.CreateDelegate 或者 Emit 构造出反射操作对应的委托,从而实现加速反射的目的。虽然本篇文章同样是讨论利用委托来加速反射调用函数,不过重点...

weixin_29476357的博客 502

告别Keil/IAR:在VSCode中用CMake+Clangd打造丝滑的STM32开发环境(附完整配置)

本文详细介绍了如何在VSCode中使用CMake和Clangd搭建高效的STM32开发环境,替代传统的Keil/IAR工具。通过完整的配置指南和快速开发技巧,帮助开发者实现轻量级、高度可定制的现代化开发流程,显著提升STM32项目的开发效率。

weixin_26843605的博客 164

Delegate.CreateDelegate 方法 创建指定类型的委托以表示指定的静态方法

下面的代码示例演示可以使用此 CreateDelegate 方法重载创建委托的两种方式。说明注意:    有两种 CreateDelegate 方法重载,它们指定 MethodInfo 但不指定第一个参数;其功能基本相同,不同之处在于一个允许您指定是否在绑定失败时引发异常,而另一个始终引发异常。此代码示例使用这两种重载。此示例声明一个 C 类和两个委托类型,前者包含一个静态方法 M2

ppkjjk1981的专栏 9145

Look4sat蓝牙追星云台

//这是一个追星云台的小程序 //配合Look4sat蓝牙传输数据(W*** A***),并让电机做出动作 //app设置内填好ESP32的蓝牙MAC,数据格式:W$AZ A$EL //希望大家可以共同改进

HoyAnGx的博客 616

Unreal5(虚幻五) 实现UI与C++代码逻辑的交互 保姆级教程

本人有Unity基础,刚学UE几天,把这一套处理流程记录一下备用。

qq_42915442的博客 9815

C# 委托(Delegate)和事件(Event)

C# 委托(Delegate)和事件(Event) 委托:是一个类,继承自System.MulticastDelegate,里面内置了几个方法。 委托可以写在类里面,也可以写在类的外面。 // 委托可以写在类的外面 public delegate void NoReturnNoParaOutClass(); public class MyDelegate { // 也可以写在类里面 public delegate void NoReturnNoPara<T>(T t);

u012577058的博客 439

Java开发者终极抉择:IntelliJ IDEA vs VS Code —— 4大维度深度对比评测

🔥关注墨瑾轩,带你探索Java的奥秘!🚀🔥超萌技术攻略,轻松晋级编程高手!🚀🔥技术宝库已备好,就等你来挖掘!🚀🔥订阅墨瑾轩,智趣学习不孤单!🚀🔥即刻启航,编程之旅更有趣!🚀在Java开发领域,选择合适的集成开发环境(IDE)对于提高开发效率和代码质量至关重要。和(简称VS Code)是两个广受好评的开发工具,各自拥有独特的特性和庞大的用户群。本篇将从多个维度深入探讨这两款IDE对Java开发者来说的优劣,包括但不限于性能、用户体验、生态系统、调试能力、以及特定Java功能的支持等方面。

java专栏 8590

C#中的“代理”和“事件”

 事件(event)是一个非常重要的概念,我们的程序时刻都在触发和接收着各种事件:鼠标点击事件,键盘事件,以及处理操作系统的各种事件。所谓事件就是由某个对象发出的消息。比如用户按下了某个按钮,某个文件发生了改变,socket上有数据到达。触发事件的对象称作发送者(sender),捕获事件并且做出响应的对象称作接收者(receiver),一个事件可以存在多个接受者。 在异步机制中,事件是线程之间进行

502

Python对象的基本组成和内存示意图及引用的本质

在Python中,变量也称为:对象的引用(reference)。变量存储的就是对象的地址。变量不需要显式声明类型。根据变量引用的对象,Python解释器自动确定数据类型。一个内存块,拥有特定的值,支持特定类型的相关操作。变量位于:栈内存(压栈出栈等细节,后续再介绍)。⚠️Python是动态类型语言。变量通过地址引用了“对象”。

Calor13的博客 557

【C语言学习疑难杂症】第20期:0x00007FF7F2821964处引发的异常0xC0000005写入位置 0x0000000000000

检查代码中是否存在野指针访问的情况,确保在进行写入操作之前,内存已经被正确分配或初始化,并且在使用完毕后进行了正确的释放。空指针访问:代码尝试在空指针地址(0x0000000000000000)处进行写入操作,导致访问冲突。检查代码中是否存在数组越界的情况,确保在进行写入操作之前,数组的索引值在合法范围内。检查代码中是否存在空指针访问的情况,确保在进行写入操作之前,指针已经被正确初始化。野指针访问:代码尝试在已释放或未初始化的内存地址进行写入操作,导致访问冲突。

学无止境 828

java 实现事件驱动_浅谈用java实现事件驱动机制

由于项目需求,需要为Java提供一套支持事件驱动机制的类库,可以实现类似于C#中的event和delegate机制。众所周知,Java语言本身以及其标准库中并没有提供事件驱动机制的相关接口,虽然Swing(我且认为其不属于标准库,因为一般没人用:)中存在相关的类支持该机制以实现组件的事件处理,但它毕竟是与GUI相耦合的,而在其它类型的应用程序中使用起来显得就有些别扭,缺乏通用性。因此有必要实现一套...

weixin_36390615的博客 1079

S7-1500 PLC与多台S7-200SMART PLC进行PROFINET通信的快捷方法

S7-1500 PLC与多台S7-200SMART PLC进行PROFINET通信的快捷方法

Robot_PLC_HMI_Automation 5686

C# delegate、event、Action、Func使用案例解析

C# 中 delegate、event、Action、Func使用案例解析 一:delegate与event配合使用 public static class Evt_Test { public static string strEquals(string str1, string str2) { Console.WriteLine(str1 + str2); return str1.Concat(str2).T

TimTiny的博客 4198

一文读懂OpenClaw:核心组件与工作原理深度解析

Agent核心:负责理解意图、规划任务、协调执行消息系统:统一的消息格式,实现组件间解耦工具注册表:可扩展的工具系统,支持自定义工具模型适配层:多模型支持,统一API接口安全机制:沙箱隔离、权限确认、操作审计性能优化:并行执行、智能缓存、增量更新理解这些核心组件和工作原理,将帮助你更好地使用OpenClaw,也为后续开发自定义扩展打下坚实基础。在下一篇文章中,我们将详细介绍OpenClaw的界面操作,包括命令行与交互模式的各种技巧。

gaoxiang_120的专栏 833

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

C# 中的delegate、event、Action、Func

都属于委托,只是展现的形式不同而已,无论哪种,其实都可以采用delegate实现,为什么会出现另外的三种呢?   因为delegate是很宽泛的,格式内容都不受限,俗话说没有规矩不成方圆,如果一人过于随意,那么他所做的事也规范不到哪去,这就会导致后期的维护很费劲,实际开发中也基本都用后面三种。 区别:   delegate:至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型。 ...

weixin_40200876的博客 4778

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

event与delegate的区别

首先,通过加入event关键字,在编译的时候编译器会自动针对事件生成一个私有的字段(与此事件相关的委托),以及两个访问器方法,即add访问器方法以及remove访问器方法,用于对事件的注册及注销(对事件使用+=及-=操作时就是调用的这两个方法)。 我想你们的问题主要是,实际上声明一个委托类型的字段也可以实现这些功能。 实际上之所以采用event而不直接采用委托,实际上还是为了封装。可以设想一下

Magina3的专栏 7482

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

c#的delegate和event

delegate是什么 委托(delegate) 是存有对某个方法的引用的一种引用类型变量,引用可在运行时被改变。如果不好理解,可以把委托理解成为函数指针,但它们是有区别的。 delegate和C++中的函数指针: 函数指针只能指向静态函数,而delegate既可以引用静态函数,又可以引用非静态成员函数。在引 用非静态成员函数时,delegate不但保存了对此函数入口指针的引用,而且还保存了...

linxinfa的专栏 2758

C#中的delegate和event

在基于Windows平台的程序设计中,事件(event)是一个很重要的概念。因为在几乎所有的Windows应用程序中,都会涉及大量的异步调用,比如响应点击按钮、处理Windows系统消息等,这些异步调用都需要通过事件的方式来完成。即使在下一代开发平台——.NET中也不例外。那么什么是事件呢?所谓事件,就是由某个对象发出的消息,这个消息标志着某个特定的行为发生了,或者某个特定的条件成立了。比如用

sam1111的专栏 2万+

C#——Delegate(委托)与Event(事件)

在刚开始学习C#的时候,常常委托与事件傻傻分不清,经常性的混为一谈。他们功能相似,应用场景却不太一样,下面就从分别的介绍再到差异的分析一起来看看啪。委托允许你将方法作为参数传递或存储,可以被直接调用。事件是一种特殊类型的委托,提供更安全、封装的订阅机制,只允许持有类触发事件(且必须是简单声明)。

我叫DP的博客 2217

Delegate、Event、Func傻傻分不清?一文带你彻底搞懂C#中的事件与委托!

c#中的事件与委托是函数的容器,可以绑定多个函数或方法,其中Event是委托的特殊实例化,而Action和Func则是对委托的两种预先封装,两者都支持多个参数的函数,区别在于Action绑定的函数无返回值,而Func绑定的函数有一个返回值。

greatming666的博客 3684

unity: C#的Action Event Delegate的异同

它们都与函数指针相关,并提供了可调用指向方法的代码块的方式。它们都是用于编写事件驱动和回调代码的通用概念。它们都可以用于实现委托模式,使触发对象与事件处理程序之间的解耦。Action和Event都是C#中的关键词,而Delegate则是一个类。Action和Func之间的区别在于Action没有返回值,而Func具有返回值。Delegate用于指向方法,而Event用于将事件与订阅器连接起来。

lejian的专栏 3810

C# 有了委托(delegate)为什么还需要事件(event)?

delegate void dowork(); // 委托申明 class Baby{ public event dowork CryEvent; // 事件成员() public void Play() { System.Console.WriteLine("孩子在玩耍..."); Thread.Sleep(2000); ...

皮皮君的博客 2546

浅谈c#中的delegate和event了

一、开篇忏悔 对自己最拿手的编程语言C#,我想对你说声对不起,因为我到现在为止才明白c#中的delegate和event是怎么用的,惭愧那。好了,那就趁着阳光明媚的早晨简单来谈谈delegate和event的简单用法吧,希望能给初学者带来帮助。PS:别像我那样学了几年c#到头来都不知道delegate和event怎么用。 二、delegate到底是什么东西 孩子,C语言总学过吧,如果你学得不...

xulong5000的专栏 221

学习C# delegate和C# event

delegate是C#中的一种类型,C# event的处理实际上是一种具有特殊签名的delegate,本文就介绍了C# delegate和C# event。 AD: 在基于Windows平台的程序设计中,事件(event)是一个很重要的概念。因为在几乎所有的Windows应用程序中,都会涉及大量的异步调用,比如响应点击按钮、处理Windows系统消息等,这些异步调用...

weixin_34321977的博客 131
上一篇: 正则表达式的内容(一)
下一篇: GridView显示带有中国式报表表头的方法
auto_ptr
博客等级 码龄20年 18粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值