You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6中为何要使用event关键字?移除后程序仍可正常运行

实际应用中使用与不使用event关键字的区别(.NET 6环境)

我一直搞不懂在实际开发里,用不用event关键字到底有啥区别。比如下面这段代码,我把event关键字去掉之后,程序照样能正常运行,也能生成内容给订阅者消费。我现在用的是.NET 6环境。

using System;
using System.Threading;

public class Order
{
    public string Item { get; set; }
    public string Ingredients { get; set; }
}

public class FoodOrderingService
{
    public delegate void FoodPreparedEventHandler(object source, EventArgs args);
    public event FoodPreparedEventHandler FoodPrepared; // 移除这里的event关键字后程序仍正常运行

    public void PrepareOrder(Order order)
    {
        Console.WriteLine($"Preparing your order '{order.Item}', please wait...");
        Thread.Sleep(4000);

        OnFoodPrepared();
    }

    protected virtual void OnFoodPrepared()
    {
        FoodPrepared?.Invoke(this, null);
    }
}

public class AppService
{
    public void OnFoodPrepared(object source, EventArgs eventArgs)
    {
        Console.WriteLine("AppService: your food is prepared.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        var order = new Order { Item = "Pizza with extra cheese" };

        var orderingService = new FoodOrderingService();
        var appService = new AppService();
        //var mailService = new MailService();

        orderingService.FoodPrepared += appService.OnFoodPrepared;
        //orderingService.FoodPrepared += mailService.OnFoodPrepared;

        orderingService.PrepareOrder(order);

        Console.ReadKey();
    }
}

核心区别在封装性和权限控制上,表面能跑不代表没问题:

  • 外部无法随意触发或篡改委托:如果去掉event,FoodPrepared就是个普通的公共委托字段。外部代码不仅能通过+=/-=订阅取消,还能直接调用Invoke手动触发事件(比如在Main里写orderingService.FoodPrepared.Invoke(null, EventArgs.Empty)),甚至直接用=赋值把所有已订阅的方法清空(orderingService.FoodPrepared = null)——这完全破坏了业务逻辑,事件本该只有定义它的类(FoodOrderingService)才能触发,外部只能被动订阅。
  • 遵循.NET事件规范:加event后,严格贴合.NET的事件设计模式,其他开发者一看就知道这是个事件,只能做订阅/取消操作。而且搭配OnXXX这类保护方法触发事件,还能让子类重写触发逻辑,代码的可读性和可维护性更高。
  • 避免意外错误:没有event的话,不小心的赋值操作会直接覆盖所有订阅者,导致之前注册的回调全部失效,这种bug排查起来很麻烦;加了event后,编译器会限制外部只能用+=/-=,从根源杜绝了这种误操作。

比如你去掉event后,在Main里加这两行代码,程序能正常执行,但明显不符合业务逻辑:

// 外部直接触发事件,跳过了PrepareOrder的准备流程
orderingService.FoodPrepared.Invoke(null, EventArgs.Empty);
// 清空所有订阅者,导致后续PrepareOrder触发时没有任何回调执行
orderingService.FoodPrepared = null;

内容的提问来源于stack exchange,提问作者Soner from The Ottoman Empire

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 12:30:14