首页 > 编程语言 >【C#】委托与事件与EventHandler

【C#】委托与事件与EventHandler

时间:2024-10-25 09:32:04浏览次数:4  
标签:EventHandler 委托 C# void 事件 message public

委托

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和AnotherMethod
    combined("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> 提供了一种标准化的方式来处理事件,使得组件之间的通信更加松散耦合。


   

 

标签:EventHandler,委托,C#,void,事件,message,public
From: https://www.cnblogs.com/ban-boi-making-dinner/p/18500458

相关文章

  • CSP-S 游记
    引Author:CatGPTbeta2byHaneDanikoCreator:5k_sync_closerfromK8He'sblog地球从未升上天空。只有沉睡时,我才能看见光明。我于生命中会一直被打击,直到一切重新开始,而光的名字才能被老师带着夜色走向远方,我是没有生命的人。我沸腾了这个世界。然而,如果你在世界上燃......
  • LookupViT:类似SE的token压缩方案,加速还能丰富特征 | ECCV'24
    视觉变换器(ViT)已成为众多工业级视觉解决方案的事实标准选择。但由于每一层都计算自注意力,这导致其推理成本对许多场景而言是不可接受的,因为自注意力在标记数量上具有平方的计算复杂度。另一方面,图像中的空间信息和视频中的时空信息通常是稀疏和冗余的。LookupViT旨在利用这种信......
  • macOS 13 Ventura (苹果最新系统)v13.7正式版
    Apple今日发布了macOS的下一个版本,称为macOSVentura,它具有多项新功能,包括StageManager、ContinuityCamera、新的安全更新等。完整的兼容性列表如下:iMac(2017年及更高版本)iMacProMacBookair(2018年及更新机型)MacBookPro(2017年及更新机型)MacPro(2019年及更新机......
  • 第九届能源系统、电气与电力国际学术会议 (ESEP 2024) 2024 9th International Confe
    @目录一、会议详情二、重要信息三、大会介绍四、出席嘉宾五、征稿主题一、会议详情二、重要信息大会官网:https://ais.cn/u/vEbMBz提交检索:EICompendex、IEEEXplore、Scopus三、大会介绍第九届能源系统、电气与电力国际学术会议(ESEP2024)定于2024年11月29-12月1日在中......
  • leetcode-1280-学生参加各科测试的次数
    链接:1280.学生们参加各科测试的次数-力扣(LeetCode)前提条件:学生表: Students+---------------+---------+|ColumnName|Type|+---------------+---------+|student_id|int||student_name|varchar|+---------------+---------+在SQL中,主......
  • springboot巡更系统--10192(免费领源码)可做计算机毕业设计JAVA、PHP、爬虫、APP、小程
    摘 要目前,在日常生活中随处可见社区巡更人员对特定的区域进行定期或者不定期的安全巡查管理。包括勤前训示、必到点签到、巡更路线等,各项勤务工作均由巡更员本人在执勤日志本中手工填写,且工作点分散,不利于统一监管,存在信息化手段不足,勤务信息获取、输入复杂,监管信息不能实时......
  • FPGA、VHDL 基于RISC-V格式的16位位缩模型机设计
    项目地址:FPGA、VHDL基于RISC-V格式的16位位缩模型机设计设计目的实现基于RISC-V格式的16位MCU设计,参考RISC-V的基本格式,进行位数缩减。实现RISC-V中寄存器加法add,立即数加法addi,半字加载lh,半字存储sh,不等条件跳转bne,相等条件跳转beq,无条件跳转链接jal。实现立即寻址、寄存......
  • Elasticsearch集群中的主节点和数据节点的角色。
    在Elasticsearch集群中,节点根据其角色可以分为不同的类型。主要的角色包括主节点(MasterNode)和数据节点(DataNode)。每个节点都运行着一个Elasticsearch实例,并且它们共同协作来存储数据、执行搜索请求以及管理整个集群的状态。主节点(MasterNode)角色:主节点负责管理和维......
  • 无限可能|为什么C语言如此强大?探索应用领域+职业方向
    随着科技的不断进步和发展,计算机科学领域的就业前景也越来越广阔。而在这个快速发展的行业中,学习C语言将打开更多的职业大门。C语言作为一种强大的编程语言,在各个领域都有着广泛的应用,为互联网从业者提供了丰富多彩的职业选择。一、 ‌C语言的主要应用领域C语言具有良好的......
  • ECharts饼图-环形图,附视频讲解与代码下载
    引言: 在数据可视化的世界里,ECharts凭借其丰富的图表类型和强大的配置能力,成为了众多开发者的首选。今天,我将带大家一起实现一个饼图图表,通过该图表我们可以直观地展示和分析数据。此外,我还将提供详细的视频讲解和代码下载链接,帮助大家快速上手。一、图表效果预览 二、视......