1

在我正在创建的程序中,我有大量的枚举

enum kEvents
{
    Start = 0,
    End,
    EntityCreated,
}

在这个程序中,有一个巨大的实体列表。每个实体都拥有一个“注册到”的“kEvents”列表

每次对象说“调用开始事件”时,我都必须遍历游戏中的每个实体,并确定它们是否在“监听”该事件。

注意:我知道 c# 有事件处理程序,但我希望从头开始创建这个枚举系统。

在这种情况下,最好的方法是:

  1. 在每个实体对象中保存枚举的集合
  2. 检查实体是否持有触发的枚举

我想知道枚举(基本上是数字)是否比List<T>对象具有更低级别、更快的处理方式。

4

3 回答 3

2

每次对象说“调用开始事件”时,我都必须遍历游戏中的每个实体,并确定它们是否在“监听”该事件。

你这样做是错的!遍历每个对象并检查它们是否已注册事件是非常低效的!这是典型的观察者设计模式,有几种方法可以解决这个问题,这里有几个:

  1. 有一个事件被引发并有一个事件类型的枚举参数(每个订阅者都得到它)。
  2. 有一个枚举和相应事件的字典。

以下是选项 1的样子:

delegate void OnEventDelegate(kEvents anEvent);
public class MyEventObservable
{
    public event OnEventDelegate OnEvent;
}

public class MyEventObserver
{
    // Constructors and all
    // ...

    public void OnEventReceived(kEvents anEvent)
    {
        switch(anEvent)
        {
            // switch through all the events and handle the ones that you need
        }
    }
}

MyEventObserver observer = new MyEventObserver();
MyEventObservable observable = new MyEventObservable();
observable.OnEvent += new OnEventDelegate(observer.OnEventReceived);

这是选项2

public class MyEventObservable
{
    private Dictionary<kEvents, List<IObserver>> _observers;
    
    MyEventObservable()
    {
        // Initialize the dictionary with all the events
    }
    
    public void RegisterObserver(kEvents event, IObserver observer)
    {
        _observers[event].Add(observer);
    }
}

interface class IObserver
{    
    void Notify(kEvents anEvent);
}

public MyEventObserver: IObserver
{
    // Constructors and all
    // ...
    
    // Override the IObserver
    public void Notify(kEvents anEvent)
    {
        switch(anEvent)
        {
            // switch through all the events and handle the ones that you need
        }
    }
}

MyEventObserver observer = new MyEventObserver();
MyEventObservable observable = new MyEventObservable();
observable.RegisterObserver(kEvents.Start, observer);

选项二将减少每个观察者必须处理的事件数量,但其代价是必须分别注册每个事件(这增加了编码复杂性)。这意味着选项 2 将工作得更快,因为要进行的函数调用更少。根据您想要获得的性能有多“疯狂”,可能还有其他选项可以帮助您加快速度,但这应该会让您走上正确的轨道。

PS 我没有编译任何代码,但它应该让你大致了解事情应该如何工作。

于 2012-04-04T00:27:01.410 回答
1

在我看来,您想实现某种发布/订阅方案,一些集中的事件接收器,实体可以订阅事件并在该事件发生时提供回调,然后其他实体会引发事件并且事件接收器会调用所有订阅该事件的实体......但我可能不明白这个问题:)

就像是:

如何访问其他类中的控件

于 2012-04-04T00:20:33.577 回答
1

每次对象说“调用开始事件”时,我都必须遍历游戏中的每个实体,并确定它们是否在“监听”该事件。

如果我正确理解了您在做什么,那么您就是在倒退。实体正在侦听哪些事件的知识不能(仅)存在于事件本身中。必须有另一个数据结构来保存这些信息。

其他数据结构可以像从枚举常量到实体列表的 Map 一样简单。

于 2012-04-04T00:29:36.923 回答