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

如何在Dictionary初始化过程中直接声明事件?

问题解答

很遗憾,C#并不支持你想要的{EventTypes.Event1, new event EventDelegate Event1}这种写法——事件是类级别的成员,必须在类的作用域内显式声明,不能在集合初始化器这类表达式上下文里临时创建或定义。

为什么不行?

事件本质是对委托的封装,它包含add和remove访问器,背后对应一个私有的委托字段。C#语法规定,事件只能作为类/结构体的成员来声明,无法通过new event这种语法在初始化器里实例化或定义。你尝试的写法既不符合事件的声明规则,也超出了集合初始化器的语法范围。

替代方案

如果你想减少重复代码,避免先声明事件再手动添加到字典的繁琐,有两种常见思路:

1. 用字典管理委托,封装事件式的访问

放弃单独声明每个事件,直接用字典存储委托实例,然后提供订阅、取消订阅和触发的方法,模拟事件的行为:

public delegate void EventDelegate(EventArgs args);
public enum EventTypes { Event1, Event2, Event3 }

private static readonly Dictionary<EventTypes, EventDelegate> _events = new Dictionary<EventTypes, EventDelegate>
{
    { EventTypes.Event1, null },
    { EventTypes.Event2, null },
    { EventTypes.Event3, null },
};

// 模拟事件的订阅
public static void Subscribe(EventTypes eventType, EventDelegate handler)
{
    if (_events.TryGetValue(eventType, out var existing))
    {
        _events[eventType] = existing + handler;
    }
}

// 模拟事件的取消订阅
public static void Unsubscribe(EventTypes eventType, EventDelegate handler)
{
    if (_events.TryGetValue(eventType, out var existing))
    {
        _events[eventType] = existing - handler;
    }
}

// 触发事件
public static void RaiseEvent(EventTypes eventType, EventArgs args)
{
    _events[eventType]?.Invoke(args);
}

这种方式的好处是不需要重复声明每个事件,所有事件都通过字典统一管理,缺点是无法使用C#原生的+=/-=事件订阅语法。

2. 保留原生事件,简化字典初始化(可选)

如果你想保留原生事件的语法支持,也可以通过反射来自动把事件添加到字典,避免手动逐个添加:

public delegate void EventDelegate();
public enum EventTypes { Event1, Event2, Event3 }

public static event EventDelegate Event1;
public static event EventDelegate Event2;
public static event EventDelegate Event3;

public static readonly Dictionary<EventTypes, EventDelegate> Events;

static YourClassName()
{
    Events = new Dictionary<EventTypes, EventDelegate>();
    // 通过反射获取所有静态事件
    var events = typeof(YourClassName).GetEvents(BindingFlags.Public | BindingFlags.Static);
    foreach (var evt in events)
    {
        if (Enum.TryParse<EventTypes>(evt.Name, out var eventType))
        {
            // 获取事件的委托实例
            var field = typeof(YourClassName).GetField(evt.Name, BindingFlags.NonPublic | BindingFlags.Static);
            if (field != null)
            {
                Events[eventType] = field.GetValue(null) as EventDelegate;
            }
        }
    }
}

这种方式保留了原生事件的+=/-=语法,同时自动完成字典的初始化,但反射会带来一点点性能开销,且代码复杂度稍高。

总结

直接在字典初始化器里声明事件的写法在C#中是不可行的,但你可以根据需求选择上述两种替代方案:要么用字典封装事件行为,要么用反射简化原生事件到字典的映射。

内容的提问来源于stack exchange,提问作者Nidere

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:39:48