【C#】委托与事件与EventHandler

委托

C# 中的委托(Delegate)是一种类型安全的函数指针,它允许你将方法作为参数传递给其他方法。委托可以引用一个或多个方法,并且可以在运行时调用这些方法。它们是实现事件和回调的基础。

 

委托的基本概念

  • 定义委托:首先需要定义一个委托类型,这指定了可被委托调用的方法签名。
  • 实例化委托:创建一个委托实例,该实例指向具体的一个或多个方法。
  • 使用委托:通过委托实例来调用其关联的方法。

 

定义委托

要定义一个委托,你需要使用 delegate 关键字。例如:

public delegate void MyDelegate(string message);

这里定义了一个名为 MyDelegate 的委托,它可以用来引用任何带有单个 string 参数并且没有返回值的方法。

 

实例化委托和使用委托

一旦定义了委托类型,你可以创建该类型的实例并让它指向某个方法。例如:

public class Program
{public static void ShowMessage(string message){Console.WriteLine(message);}public static void Main(){// 创建委托实例并指向ShowMessage方法MyDelegate myDelegate = new MyDelegate(ShowMessage);// 通过委托调用方法myDelegate("Hello, World!");}
}

在这个例子中,myDelegate 是一个委托实例,它被初始化为指向 ShowMessage 方法。之后可以通过 myDelegate 来间接调用 ShowMessage 方法。

 

多播委托

C# 中的委托还支持多播(即一个委托对象可以包含对多个方法的引用)。当你调用一个多播委托时,所有绑定到该委托的方法都会按顺序执行。

public static void AnotherMethod(string message)
{Console.WriteLine($"Another: {message}");
}public static void Main()
{MyDelegate first = new MyDelegate(ShowMessage);MyDelegate second = new MyDelegate(AnotherMethod);// 合并两个委托MyDelegate combined = first + second;// 调用combined会依次执行ShowMessage和AnotherMethodcombined("Hello, Multicast!");
}

 

事件

事件是一个使用event关键字声明的成员,它基于委托类型

你可以自定义一个委托类型并使用它来定义事件。

 

事件的基本概念

  1. 事件的拥有者:这是声明事件的对象或类。例如,在一个计时器类中,计时器本身是事件的拥有者。

  2. 事件本身:这是一个使用event关键字声明的成员,它基于委托类型。当特定条件满足时,事件会被触发(即调用所有注册到该事件的处理方法)。

  3. 事件处理器:这是响应事件的方法。它们是与事件关联的函数,当事件被触发时,这些方法将被执行。

  4. 事件订阅:这是将事件处理器添加到事件的过程。通过+=操作符来完成订阅,而-=操作符用来取消订阅。

  5. 事件触发:这是执行所有已注册的事件处理器的行为。通常是通过调用委托实例来实现的。

 

事件的工作原理

  • 当一个事件被定义后,它可以像字段一样被初始化,但它是不可直接访问的(只能通过+=-=进行订阅/退订)。这是因为event关键字提供了额外的封装,确保了外部代码不能直接修改事件的内部状态。

  • 事件本质上是一个委托类型的字段,这意味着它可以指向一个或多个方法。当事件被触发时,所有注册到该事件的方法都会按顺序执行。

  • 事件通常会携带一些数据给事件处理器。这通过创建自定义的EventArgs派生类来实现,然后将其作为参数传递给事件处理器。

 

自定义委托和事件

这里是一个例子,展示如何创建自定义委托和事件:

首先,定义一个自定义委托:

// 定义一个自定义委托
public delegate void CustomEventHandler(string message);

然后,可以在类中使用这个自定义委托来定义一个事件:

public class EventPublisher
{// 使用自定义委托定义一个事件public event CustomEventHandler CustomEvent;// 保护方法用于触发事件protected virtual void OnCustomEvent(string message){CustomEvent?.Invoke(message);}// 产生事件的动作public void DoSomething(){Console.WriteLine("Doing something...");// 在某些条件下触发事件OnCustomEvent("Something happened!");}
}

最后,在客户端代码中订阅和处理这个事件:

class Program
{static void Main(){var publisher = new EventPublisher();// 订阅事件publisher.CustomEvent += (message) => Console.WriteLine($"Custom Event received: {message}");// 执行操作,可能会触发事件
        publisher.DoSomething();}
}

在这个例子中,CustomEventHandler 是一个自定义的委托类型,而 CustomEvent 是一个基于这个委托类型的事件。客户端代码可以像使用 EventHandler<TEventArgs> 那样使用 += 来订阅这个事件。

 

EventHandler

在 C# 中,EventHandler 是一种特殊的委托类型,专门用于事件处理。它定义在 System 命名空间中,并且通常用来实现发布-订阅模式,这是 .NET 框架中处理事件的标准方式。

EventHandler 的定义如下:

public delegate void EventHandler(object sender, EventArgs e);

这里有几个关键点需要注意:

  1. sender 参数:这是一个 object 类型的参数,代表触发事件的对象。这通常是发出事件的那个对象实例(比如一个按钮控件)。

  2. EventArgs 参数:这是一个 EventArgs 类型的参数,提供了与事件相关的数据。对于不需要传递额外信息的基本事件,可以使用这个基类。如果需要携带更多信息,则可以继承自 EventArgs 创建特定的事件参数类。

使用示例

下面是一个简单的例子,展示如何使用 EventHandler 来定义和处理事件:

using System;// 定义一个自定义的EventArgs类来携带额外的数据
public class MyEventArgs : EventArgs
{public string Message { get; set; }public MyEventArgs(string message){Message = message;}
}// 一个类,包含一个事件
public class EventPublisher
{// 定义事件public event EventHandler<MyEventArgs> MyEvent;// 触发事件的方法protected virtual void OnMyEvent(MyEventArgs e){MyEvent?.Invoke(this, e);}// 产生事件的动作public void DoSomething(){Console.WriteLine("Doing something...");// 在某些条件下触发事件OnMyEvent(new MyEventArgs("Something happened!"));}
}class Program
{static void Main(){var publisher = new EventPublisher();// 订阅事件publisher.MyEvent += (sender, e) => Console.WriteLine($"Event received: {e.Message}");// 执行操作,可能会触发事件
        publisher.DoSomething();}
}

在这个例子中:

  • 我们定义了一个 MyEventArgs 类来携带事件数据。
  • EventPublisher 类有一个 MyEvent 事件,当调用 DoSomething 方法时,该事件会被触发。
  • 在主程序中,我们创建了 EventPublisher 的一个实例,并为 MyEvent 事件添加了一个处理器(lambda 表达式),该处理器将在事件被触发时打印一条消息。

通过这种方式,EventHandler 和它的泛型版本 EventHandler<TEventArgs> 提供了一种标准化的方式来处理事件,使得组件之间的通信更加松散耦合。


 
 

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

10.23 测试用例

设计测试用例编写技巧 ================================= 一、查看用例的模板 案例模板1:案例模板2:案例3:========================================== 二、用例的要素讲解 .编写用例的要素? 用例编号,用例标题,前置条件,测试步骤,预期结果,优先级 (必写) 系统名称…

CSP-S 游记

2024.10.25 / Day0 做梦梦见自己码了一套线段树合并加线段树分裂,被人 D 为什么不直接写 fhq,我觉得他说的有道理 早上五点半迷迷糊糊醒了,冷得我要死,睡不着一点,所以度过了比较漫长的半小时 早上起床依旧是逆天发言盖脸 不是,怎么会有人觉得我只要早读就不困了,一早读…

【shiro】13.验证码过滤器

通过之前的学习,我们知道如果自定义过滤器的使用。接下来,查看ruoyi源码,我们需要在过滤器中实现验证码。 前提已新建SpringBoot项目 项目以成功集成shiro,并完成简单配置 已完成路由配置,包含登录页面/login和首页index 已经知道如何使用和自定义过滤器思路 1. Shiro的配…

macOS 13 Ventura (苹果最新系统)v13.7正式版

Apple 今日发布了 macOS 的下一个版本,称为macOS Ventura,它具有多项新功能,包括 Stage Manager、Continuity Camera、新的安全更新等。完整的兼容性列表如下:iMac(2017 年及更高版本) iMac Pro MacBook air(2018 年及更新机型) MacBook Pro(2017 年及更新机型) Mac …

蓝桥杯大赛 ——首场算法团队战题解

1. 不同角度【算法赛】 在生活中,我们总是根据数值的大小来判断两个数字的大小关系。例如,9999 总是小于 100100,999999 总是小于 10001000。但如果我们换一个角度,将 999999 和 10001000 看成是两个数字字符串,并用字典序来比较它们的大小,那么此时,999999 将大于 1000…

挖宝国内良心核心期刊,免审稿费,免版面费,还有奖励,更有温度

❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀ https://blog.csdn.net/u011344545/article/details/143167586 github:https://github.com/MichaelBeechanCSDN:https://blog.csdn.net/u011344545 ❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀ 话说科研…

HarmonyOS:基于Web组件构建网络应用(1)

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤博客园地址:为敢技术(https://www.cnblogs.com/strengthen/ )➤GitHub地址:https://github.com/strengthen➤原文地址:https://www.cnblogs.com/strengthen/p/18499435➤如果链接不是为敢技术的博…

关于决策树的理解

近期在项目中使用了规则树这一设计模式,感觉和决策链来说是有些区别的 1.决策链是链型的,走的是链,流程都要完整的走一遍 2.决策链用的一种嵌套,基于函数结尾重新调用next的函数直至结束 但是规则树不一样 规则树是基于类似二叉树的结构,有的通过有的不通过 ,并且它每层都用Lis…

半导体晶圆厂如何保持 可靠安全又高效的跨网文件交换?

晶圆厂是半导体产业链最重要的一环,它位于半导体制造的中游,在这个过程中,IC设计公司将芯片设计正式进行投产,晶圆厂制造晶圆后,再应用于下游的汽车、手机、通信等不同行业。 半导体晶圆厂为了数据安全,通常会进行网络隔离,对于大型晶圆厂,网络隔离会非常细致,如晶圆…

Abp-VNext用户权限管理系列文章---工作流

一、工作流的使用 1、工作流定义图,我们定义了一个订单的工作审批流2、创建的可以审批的用户,密码都为Bridge0 发起流程:用户wf_order_creator 订单创建员 采购科员审核:角色: 采购科员 用户:wf_order_officer +订单审核科员 采购科长审核: wf_order_deptHead 订…

进入网站后台修改不了?模板网站能修改代码吗?

大多数模板网站允许用户在一定范围内自定义和修改代码,尤其是对于HTML、CSS和JavaScript等前端代码。 限制与权限:一些模板网站可能对代码编辑有特定的限制,例如仅允许修改样式或内容,而不允许更改结构或添加复杂的脚本。 高级功能:部分高级模板服务提供更灵活的代码编辑选…

网站模板修改上传图片?模板如何修改网站logo?

确定图片上传的位置确定在网站的哪个部分需要添加图片上传功能,例如用户资料页面、产品详情页等。HTML 表单设置在需要上传图片的地方添加一个表单,使用 <form> 标签,并确保 enctype 属性设置为 multipart/form-data,这允许文件数据被正确编码。<form action=&quo…