C# 委托与事件介绍

news/2025/2/6 18:20:20 标签: c#, 开发语言

.NET学习资料

.NET学习资料

.NET学习资料


在 C# 编程中,委托(Delegate)与事件(Event)是两个重要且紧密相关的概念,它们为程序提供了强大的灵活性和可扩展性,尤其在实现代码之间的松散耦合和事件驱动编程方面发挥着关键作用。

一、委托

(一)定义

委托是一种引用类型,它定义了方法的签名,即方法的参数列表和返回类型。简单来说,委托可以看作是对方法的一种 “抽象引用”,允许将方法作为参数传递给其他方法,或者将方法赋值给变量 。这就好比在 C 或 C++ 中函数的指针,但委托是类型安全且完全面向对象的,克服了指针可能带来的安全隐患。例如,定义一个简单的委托类型:

public delegate void GreetingDelegate(string name);

上述代码定义了一个名为GreetingDelegate的委托,它指向的方法接受一个string类型的参数,并且没有返回值。

(二)特点

方法作为参数传递:委托最大的特点之一就是允许将方法当作另一个方法的参数进行传递,从而实现代码的动态行为。例如:

public void GreetPeople(string name, GreetingDelegate MakeGreeting)
{
    MakeGreeting(name);
}

在这个方法中,GreetPeople接受一个GreetingDelegate类型的参数MakeGreeting,在调用GreetPeople时,可以传入不同的方法,如EnglishGreeting或ChineseGreeting,动态决定具体的问候方式。

private static void EnglishGreeting(string name)
{
    Console.WriteLine("Morning, " + name);
}
private static void ChineseGreeting(string name)
{
    Console.WriteLine("早上好, " + name);
}
// 调用GreetPeople方法,传入不同的问候方法
GreetPeople("Jimmy Zhang", EnglishGreeting);
GreetPeople("张子阳", ChineseGreeting);

可用于定义回调方法:在异步编程或需要在特定操作完成后执行某些代码的场景中,委托可以用来定义回调方法。比如,在进行异步网络请求时,当请求完成后,可以通过委托指定一个回调方法来处理返回的数据。

可以链接多个方法:委托对象可以通过+和-运算符来添加或移除方法,从而实现将多个方法链接在一起。当委托被调用时,会依次调用链接的所有方法 。例如:

public delegate void NumberChanger(int n);
public class ClassC
{
    public static event NumberChanger changer;
    public static void Test()
    {
        changer(100);
    }
}
public class Class2
{
    public static void ClassA_Test(int i)
    {
        Console.WriteLine("Class2:" + i);
    }
}
public class Class3
{
    public static void ClassA_Test(int i)
    {
        Console.WriteLine("Class3:" + i);
    }
}
// 链接多个方法
ClassC.changer += Class2.ClassA_Test;
ClassC.changer += Class3.ClassA_Test;
ClassC.Test();

上述代码中,ClassC.changer委托对象链接了Class2.ClassA_Test和Class3.ClassA_Test两个方法,当调用ClassC.Test()触发changer委托时,这两个方法会依次被执行。

(三)使用步骤

定义委托类型:根据需要调用的方法签名,定义一个委托类型。委托类型的参数列表和返回类型必须与要调用的方法一致。

创建委托对象实例:创建委托对象的实例,使其指向要调用的方法。可以通过直接赋值的方式,将方法名赋给委托对象。

将委托对象作为参数传递:在需要调用方法的地方,将委托对象作为参数传递给其他方法,从而实现对目标方法的调用。

二、事件

(一)定义

事件是一种特殊的委托,它基于委托机制,为委托提供了一个发布 / 订阅机制 。简单来说,事件允许对象向外部订阅者通知特定事件的发生,订阅者可以响应这些事件。在 C# 中,使用event关键字来声明事件。例如:

public delegate void MyEventHandler(object sender, EventArgs e);
public class MyClass
{
    public event MyEventHandler MyEvent;
    // 触发事件的方法
    protected virtual void OnMyEvent(EventArgs e)
    {
        MyEvent?.Invoke(this, e);
    }
}

上述代码中,首先定义了一个MyEventHandler委托,然后在MyClass类中声明了一个MyEvent事件,该事件的类型为MyEventHandler。OnMyEvent方法用于触发MyEvent事件,在触发事件时,会调用所有订阅了该事件的方法。

(二)特点

事件只能在声明它的类内部触发:这是事件与委托的一个重要区别。事件的触发通常是由类内部的某些操作引起的,例如属性值的改变、某个任务的完成等。外部类无法直接触发事件,只能通过订阅事件来响应事件的发生。

用于外部接口和通知机制:事件主要用于类向外部提供一种通知机制,当类内部发生特定事件时,通知外部订阅者。例如,在图形用户界面(GUI)编程中,按钮的点击事件、窗口的关闭事件等,都是通过事件来通知程序的其他部分进行相应的处理。

基于委托机制:事件本质上是基于委托实现的,它使用委托来管理订阅者列表,并在事件发生时向所有订阅者触发方法调用。

(三)使用步骤

在类中定义事件:使用event关键字在类中定义一个事件,事件的类型必须是已定义的委托类型。

订阅者订阅事件:外部订阅者通过+=运算符将方法添加到事件中,实现对事件的订阅。例如:

MyClass myObj = new MyClass();
myObj.MyEvent += new MyEventHandler(MyEventHandlerMethod);

上述代码中,MyEventHandlerMethod是订阅者定义的处理事件的方法,通过+=运算符将其添加到myObj.MyEvent事件中。

事件触发和处理:当类内部满足事件触发条件时,调用触发事件的方法,此时会自动调用所有订阅者的事件处理方法。在事件处理方法中,可以编写相应的逻辑来处理事件。例如:

// 触发事件
myObj.OnMyEvent(new EventArgs());

上述代码中,调用myObj.OnMyEvent方法触发MyEvent事件,从而调用MyEventHandlerMethod方法进行事件处理。

三、委托与事件的关系

委托是事件的底层机制,事件依赖于委托来实现其功能。事件使用委托来管理订阅者列表,当事件发生时,通过委托调用所有订阅者的方法 。可以说,事件是在委托基础上的一种更高级的抽象,它为委托提供了更安全、更方便的使用方式,主要用于实现对象之间的事件通知和交互。

在实际编程中,委托和事件经常一起使用。例如,在实现观察者模式时,被观察者可以通过事件来通知观察者状态的变化,而委托则用于定义事件的处理方法签名和实现事件的调用机制。通过委托和事件的结合使用,可以实现代码的高度解耦和可维护性,提高程序的灵活性和可扩展性。

总之,委托和事件是 C# 编程中非常重要的概念,理解和掌握它们的使用方法对于编写高质量、可维护的 C# 程序至关重要。无论是在桌面应用程序开发、Web 应用程序开发还是其他类型的软件开发中,委托和事件都有着广泛的应用场景。希望通过本文的介绍,能帮助你更好地理解和运用 C# 中的委托与事件。


http://www.niftyadmin.cn/n/5843247.html

相关文章

[Java]函数式编程

Lambda函数 JDK8新增的语法形式, 使用Lambda函数替代某些匿名内部类对象,从而让程序代码更简洁,可读性更好。 基本使用 lambda表达式只能简化函数式接口的匿名内部类写法 // 1.定义抽象类 abstract class Animal {public abstract void crt(); }publi…

【Elasticsearch】geohex grid聚合

在 Elasticsearch 中,地理边界过滤是一种用于筛选地理数据的技术,它可以根据指定的地理边界形状(如矩形、多边形等)来过滤符合条件的文档。这种方法在地理空间数据分析中非常有用,尤其是在需要将数据限制在特定地理区域…

【Elasticsearch】 邻接矩阵聚合(Adjacency Matrix Aggregation)

Elasticsearch 的邻接矩阵聚合(Adjacency Matrix Aggregation)是一种特殊的桶聚合,用于分析多个过滤器之间的交集关系。它可以帮助你快速了解哪些文档同时满足多个条件,并统计每个交集的文档数量。这种聚合特别适用于分析复杂的关…

一款wordpress AI免费插件自动内容生成+前端AI交互+文章批量采集

一款wordpressAI自动内容生成前端AI会话窗口交互文章批量采集免费插件 1. SEO优化文章生成 关键词驱动的内容生成:用户可以输入关键词或长尾关键词,插件会根据这些关键词生成高质量的SEO优化文章。文章结构清晰,语言自然流畅,符合…

【大数据技术】搭建完全分布式高可用大数据集群(Scala+Spark)

搭建完全分布式高可用大数据集群(Scala+Spark) scala-2.13.16.tgzspark-3.5.4-bin-without-hadoop.tgz注:请在阅读本篇文章前,将以上资源下载下来。 写在前面 本文主要介绍搭建完全分布式高可用集群Spark的详细步骤。 注意: 统一约定将软件安装包存放于虚拟机的/softwa…

景联文科技:专业数据采集标注公司 ,助力企业提升算法精度!

随着人工智能技术加速落地,高质量数据已成为驱动AI模型训练与优化的核心资源。据统计,全球AI数据服务市场规模预计2025年突破200亿美元,其中智能家居、智慧交通、医疗健康等数据需求占比超60%。作为国内领先的AI数据服务商,景联文…

mini-lsm通关笔记Week2Day6

项目地址:https://github.com/skyzh/mini-lsm 个人实现地址:https://gitee.com/cnyuyang/mini-lsm Summary 在本章中,您将: 实现WAL日志文件的编解码 系统重启时使用WAL日志恢复memtable 要将测试用例复制到启动器代码中并运行…

深度学习篇---二维码预训练模型

文章目录 前言第一部分:二维码1. 二维码结构定位标记分隔符定时标记格式信息数据码字纠错码字 2. 二维码识别步骤步骤一:图像预处理灰度化二值化 步骤二:定位标记检测查找定位标记确定二维码位置和方向 步骤三:图像校正透视变换 步…