简体   繁体   English

如何在字典初始化中声明事件?

[英]How to declare events inside a dictionary initialization?

I am creating a Dictionary of events and I want to declare those events inside the initialization of that dictionary instead of declaring them somewhere else and placing the links to the dictionary.我正在创建一个事件字典,我想在该字典的初始化中声明这些事件,而不是在其他地方声明它们并将链接放置到字典中。

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

    public enum EventTypes
    {
        Event1, 
        Event2,
        Event3,
    }

    public static Dictionary<EventTypes, EventDelegate> events = new Dictionary<EventTypes, EventDelegate>
    {
        {EventTypes.Event1, Event1},
        {EventTypes.Event2, Event2},
        {EventTypes.Event3, Event3},
    };

So I want to do something like that:所以我想做这样的事情:

{EventTypes.Event1, new event EventDelegate Event1}

Is that possible?那可能吗?

How about wrapping the events? 包装活动怎么样?

class MyEventWrapper
{
    public event EventDelegate Handlers;

    public void Raise(object sender, EventArgs args)
    {
        Handlers?.Invoke(sender, args);
    }
}

//

Dictionary<EventTypes, MyEventWrapper> eventMap = new Dictionary<EventTypes, MyEventWrapper>
{
    { EventTypes.Event1, new MyEventWrapper() },
    { EventTypes.Event2, new MyEventWrapper() },
};

//

eventMap[EventTypes.Event1].Handlers += (s, a) => { };
eventMap[EventTypes.Event2].Handlers += (s, a) => { };

//

eventMap[EventTypes.Event1].Raise(this, new EventArgs());

You could declare an empty bodied delegate with the signature of your EventDelegate , and use it for the initialization of the dictionary items. 您可以使用EventDelegate的签名声明一个空身体委托,并将其用于字典项的初始化。

public delegate void EventDelegate(object data);
public static readonly EventDelegate EventDelegateEmptyBody = (_) => { };

public static Dictionary<EventTypes, EventDelegate> Events = new Dictionary<EventTypes, EventDelegate>
{
    {EventTypes.Event1, EventDelegateEmptyBody},
    {EventTypes.Event2, EventDelegateEmptyBody},
    {EventTypes.Event3, EventDelegateEmptyBody},
};

The downside is that this empty method will be invoked every time an event is raised, so you'll lose some performance. 缺点是每次引发事件时都会调用此空方法,因此您将失去一些性能。 The upside is that you will not need to check if the delegate is empty before invoking it. 好处是,在调用委托之前,您无需检查委托是否为空。 It will never be empty. 它永远不会是空的。

Instead of an empty method you could have a method that actually do something, like logging the raising of an event. 您可以使用实际执行某些操作的方法,而不是使用空方法,例如记录事件的引发。


Sample code demonstrating the usage of the Events dictionary: 示例代码演示了Events字典的用法:

Events[EventTypes.Event1] += (object data) =>
{
    Console.WriteLine($"Event1 first handler: {data}");
};
Events[EventTypes.Event1] += (object data) =>
{
    Console.WriteLine($"Event1 second handler: {data}");
};
Events[EventTypes.Event2] += (object data) =>
{
    Console.WriteLine($"Event2 handler: {data}");
};

Events[EventTypes.Event1].Invoke("test1");
Events[EventTypes.Event2].Invoke("test2");
Events[EventTypes.Event3].Invoke("test3");

Console output: 控制台输出:

Event1 first handler: test1
Event1 second handler: test1
Event2 handler: test2

Update: It seems that the empty bodied delegate is redundant. 更新:似乎空身体代表是多余的。 The Events dictionary can be initialized with null values, and works just fine. 可以使用空值初始化Events字典,并且工作得很好。

public static Dictionary<EventTypes, EventDelegate> Events = new Dictionary<EventTypes, EventDelegate>
{
    {EventTypes.Event1, null},
    {EventTypes.Event2, null},
    {EventTypes.Event3, null},
};

The only difference is that we must check for null before raising the events (the null conditional operator makes it easy). 唯一的区别是我们必须在引发事件之前检查null(null条件运算符使其变得容易)。

Events[EventTypes.Event1]?.Invoke("test1");
Events[EventTypes.Event2]?.Invoke("test2");
Events[EventTypes.Event3]?.Invoke("test3");

If you define your dictionary like this: 如果你这样定义你的字典:

public delegate void EventDelegate(object data);

public static Dictionary<EventTypes, EventDelegate> Events =
    new Dictionary<EventTypes, EventDelegate>
    {
        { EventTypes.Event1, (EventDelegate)((_) => { }) },
        { EventTypes.Event2, (EventDelegate)((_) => { }) },
        { EventTypes.Event3, (EventDelegate)((_) => { }) },
    };

public enum EventTypes
{
    Event1,
    Event2,
    Event3,
}

Then this code works a treat: 那么这段代码就是一种享受:

Events[EventTypes.Event1] += (object data) => Console.WriteLine($"Event1 (1): {data}");
Events[EventTypes.Event1] += (object data) => Console.WriteLine($"Event1 (2): {data}");
Events[EventTypes.Event2] += (object data) => Console.WriteLine($"Event2: {data}");

Events[EventTypes.Event1]("A");
Events[EventTypes.Event2]("B");
Events[EventTypes.Event3]("C");

The output I get is: 我得到的输出是:

Event1 (1): A
Event1 (2): A
Event2: B

You are then clearly declaring those events inside the initialization of the dictionary. 然后,您可以在字典初始化中明确声明这些事件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM