如何确保C#中的List始终具有特定元素?

时间:2015-06-09 19:35:55

标签: c# list elements

我有一个名为GameObject的类,它有一个动态的组件列表。可以随时删除和添加这些组件。组件可能是纹理,声音或转换等。确保此列表始终具有一个Transition组件的最佳方法是什么?每种类型只允许一个组件。

我脑子里有两个可能的解决方案。哪一个是最好的? 有没有更好的解决方案来解决这个问题?

方法1:

ref

方法2:

class GameObject {
    private List<Component> components;

    public T GetComponent<T>() where T : Component {
        // search the requested component and return it
        foreach(Component comp in components) {
            if(comp is T) return (T)comp;
        }
        // return null or throw exception when not found
        return null;
    }

    public void RemoveComponent<T>() where T : Component {
        if(typeof(T) != typeof(Transition)) {
            // only remove the componenent if it's not a Transition component
            Component tmp;
            foreach(Component comp in components) {
                if(comp is T) tmp = comp;
                break;
            }
            components.Remove(tmp);
        }
    }
}

1 个答案:

答案 0 :(得分:5)

似乎您正在尝试创建所谓的实体组件模型。我建议分析一些使用该模型的引擎,例如 Paradox Game Engine

Entity(GameObject)和PropertyContainer(组件集合)应该是您特别感兴趣的。

将转换组件作为单独的字段保存并将其存储在组件列表中可能是个好主意。由于它保证是每个游戏对象的一部分,因此您可以提供单独的getter属性,以便直接访问此组件以绕过任何查找成本。

由于您似乎每个类型只允许一个组件,因此将组件存储在Dictionary<Type, Component>中会很有效。与迭代组件和进行类型比较相比,这将提供非常快速的查找。

第二种方法的略微修改版本:

class GameObject
{        
    private readonly Transition transition = new Transition();
    private readonly Dictionary<Type, Component> components = new Dictionary<Type, Component>();        

    public GameObject()
    {
        AddComponent(transition);
    }

    public Transition Transition { get { return transition; } }

    public T GetComponent<T>() where T : Component
    {
        Component component;
        if (components.TryGetValue(typeof (T), out component))
        {
            return (T) component;
        }
        return null;
    }

    public void AddComponent<T>(T component) where T : Component
    {
        Type type = typeof (T);
        if (!components.ContainsKey(type))
        {
            components.Add(type, component);
        }
    }

    public void RemoveComponent<T>() where T : Component
    {                        
        if (typeof(T) != typeof(Transition))
        {
            components.Remove(typeof (T));                
        }
    }
}