C#的事件机制怎么理解?

来源:网络学院作者:小鱼头衔:草根站长
导读:本期聚焦于小伙伴创作的《C#的事件机制怎么理解?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#的事件机制怎么理解?》有用,将其分享出去将是对创作者最好的鼓励。

C#的事件机制是一种基于委托的特殊成员,主要用于实现对象之间的消息通知,让发布事件的对象不需要知道接收事件的对象具体是谁,降低代码之间的耦合度。

C#的事件机制怎么理解?

事件和委托的关系

事件本质上是对委托的封装,委托定义了方法的签名,事件则限制了外部对委托实例的操作权限。委托可以被直接赋值、调用,而事件只能在声明它的类内部触发,外部只能进行订阅和取消订阅操作。

可以把委托理解为方法的容器,事件就是这个容器的对外暴露的受限接口,避免外部随意修改委托的调用列表或者触发委托。

事件机制的核心组成

一个完整的事件机制通常包含四个部分:

  • 事件发布者:定义事件、触发事件的对象
  • 事件订阅者:注册事件处理逻辑的对象
  • 事件参数:传递事件相关信息的自定义类,通常继承自EventArgs
  • 事件委托:定义事件处理方法的签名

自定义事件的实现步骤

1. 定义事件参数类

如果需要传递事件相关的数据,需要先定义继承自EventArgs的参数类:

using System;

// 自定义事件参数,携带消息内容
public class MessageEventArgs : EventArgs
{
    public string Message { get; set; }
    
    public MessageEventArgs(string message)
    {
        Message = message;
    }
}

2. 定义事件发布者类

发布者类中需要定义委托、基于委托的事件,以及触发事件的方法:

using System;

public class MessagePublisher
{
    // 定义事件委托,签名需要和事件处理方法匹配
    public delegate void MessageEventHandler(object sender, MessageEventArgs e);
    
    // 定义事件,基于上面的委托
    public event MessageEventHandler MessagePublished;
    
    // 触发事件的方法,通常命名为On+事件名,且为protected virtual方便子类重写
    protected virtual void OnMessagePublished(MessageEventArgs e)
    {
        // 检查事件是否有订阅者,避免空引用异常
        MessagePublished?.Invoke(this, e);
    }
    
    // 发布消息的方法,内部触发事件
    public void PublishMessage(string content)
    {
        Console.WriteLine($"发布者发布消息:{content}");
        MessageEventArgs args = new MessageEventArgs(content);
        OnMessagePublished(args);
    }
}

3. 定义事件订阅者类

订阅者类需要定义和事件委托签名匹配的处理方法:

using System;

public class MessageSubscriber
{
    public string Name { get; set; }
    
    public MessageSubscriber(string name)
    {
        Name = name;
    }
    
    // 事件处理方法,签名需要和MessageEventHandler委托一致
    public void HandleMessage(object sender, MessageEventArgs e)
    {
        Console.WriteLine($"{Name} 收到消息:{e.Message}");
    }
}

4. 调用实现事件交互

在主程序中完成事件的订阅和触发:

using System;

class Program
{
    static void Main(string[] args)
    {
        // 创建发布者
        MessagePublisher publisher = new MessagePublisher();
        
        // 创建两个订阅者
        MessageSubscriber subscriber1 = new MessageSubscriber("订阅者A");
        MessageSubscriber subscriber2 = new MessageSubscriber("订阅者B");
        
        // 订阅事件,把处理方法注册到事件的调用列表
        publisher.MessagePublished += subscriber1.HandleMessage;
        publisher.MessagePublished += subscriber2.HandleMessage;
        
        // 发布者发布消息,触发事件
        publisher.PublishMessage("今天天气很好");
        
        // 取消订阅者A的订阅
        publisher.MessagePublished -= subscriber1.HandleMessage;
        
        Console.WriteLine("取消订阅者A后再次发布消息:");
        publisher.PublishMessage("明天要下雨");
    }
}

事件使用的注意事项

  • 触发事件前一定要检查事件是否为null,避免没有订阅者时触发导致空引用异常,C# 6.0及以上可以使用?.语法简化判断
  • 事件只能在声明它的类内部触发,外部无法直接调用事件,这是事件和委托的核心区别之一
  • 事件参数类建议继承自EventArgs,这是C#的事件设计规范,方便统一事件参数的结构
  • 不需要使用事件时,及时取消订阅,避免订阅者对象无法被垃圾回收,导致内存泄漏

内置事件的使用示例

C#的很多内置类都提供了事件,比如按钮的Click事件,下面的示例演示了控制台模拟按钮点击的逻辑:

using System;

// 模拟按钮类
public class MyButton
{
    // 定义点击事件,使用内置的EventHandler委托,它默认接收object和EventArgs参数
    public event EventHandler Click;
    
    protected virtual void OnClick(EventArgs e)
    {
        Click?.Invoke(this, e);
    }
    
    // 模拟按钮被点击
    public void SimulateClick()
    {
        Console.WriteLine("按钮被点击");
        OnClick(EventArgs.Empty);
    }
}

class Test
{
    static void Main(string[] args)
    {
        MyButton button = new MyButton();
        // 订阅点击事件
        button.Click += (sender, e) => Console.WriteLine("按钮点击处理逻辑执行");
        // 模拟点击
        button.SimulateClick();
    }
}

C#eventdelegate事件订阅事件发布修改时间:2026-07-13 09:03:26

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。