如何确保c#中的List总是有一个特定的元素

本文关键字:有一个 元素 List 中的 何确保 确保 | 更新日期: 2023-09-27 17:54:50

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

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

方法1:

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);
        }
    }
}

方法2:

class GameObject {
    // separate variable for the transition component
    private Transition transition;
    private List<Component> components;
    public T GetComponent<T>() where T : Component {
        // if a transition is requestet just return it
        if(typeof(T) == typeof(Transition)) {
            return transition;
        }
        // else: search the requested component in the list
        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);
        }
    }
}

如何确保c#中的List总是有一个特定的元素

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

实体(游戏对象)和属性容器(组件集合)应该是你特别感兴趣的。

将转换组件保留为单独的字段并将其存储在组件列表中可能是一个好主意。因为它是每个游戏对象的一部分,你可以提供一个单独的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));                
        }
    }
}