包含接口的两个列表与包含具有两个接口的结构的一个List

时间:2015-12-14 13:56:57

标签: c#

我有两个接口。 ICacheHolder将由一个实现游戏对象和IVisualizer逻辑的类实现,它将成为可视化表示。

public interface ICacheHolder
{
    void updateCacheWithCurrentState(int chachFrame);

    void resizeCache(int newSize);

    T getCacheFrame<T>(int cacheIndex, float interpolationToNext) where T : struct;
}

public interface IVisualizer
{
    void updateVisualization(ICacheHolder cacheHolder, int cacheIndex, float interpolation);
}

每个ICacheHolder连接到一个IVisualizer对象,关系是1比1。 我正在尝试确定它是否更好(性能/内存方面)将它们存储在两个单独的列表中或作为结构存储在一个列表中。会有很大的不同吗?如果我使用struct版本会发生拳击吗?我重新调整列表的大小将从100到1000。

版本1:

public class CacheFramework
{
private List<ICacheHolder> cacheHolders = new List<ICacheHolder>();
private List<IVisualizer> visualizers = new List<IVisualizer>();
...
}

第2版:

struct SimulationObject
{
    public ICacheHolder CacheHolder;
    public IVisualizer Visualizer;
}
public class CacheFramework
{
private List<SimulationObject> cacheHolder = new List<SimulationObject>();
...
}

添加和删除等操作不会经常进行。只有在游戏开始时才会有很多添加电话。

版本1:

private bool AddSimulationObject(ICacheHolder cacheHolder, IVisualizer visualizer)
{
    if (!cacheHolders.Contains(cacheHolder) && !visualizers.Contains(visualizer))
    {
        cacheHolders.Add(cacheHolder);
        visualizers.Add(visualizer);
        return true;
    }
    return false;
}

第2版:

private bool AddSimulationObject(ICacheHolder cacheHolder, IVisualizer visualizer)
{
    int index = simulationObjects.FindIndex(
        delegate (SimulationObject simulationObject)
        {
            return simulationObject.CacheHolder == cacheHolder || simulationObject.Visualizer == visualizer;
        }
        );

    if (index >= 0 )
    {
        SimulationObject newObject;
        newObject.CacheHolder = cacheHolder;
        newObject.Visualizer = visualizer;
        return true;
    }
    return false;
}

至少会访问列表    通过其索引的每一帧。

其他信息: 使用ICacheHolder的每个类都将包含一个List<struct>,其中包含位置,旋转或健康等数据。每个列表元素都是及时的快照。目标是来回穿梭时间。

修改1:

修正了AddSimulationObject Version 2中的错误。

正如AddSimulationObject Version 2所指出的那样:

private bool AddSimulationObject(ICacheHolder cacheHolder, IVisualizer visualizer)
{
    SimulationObject newObject = new SimulationObject { CacheHolder = cacheHolder, Visualizer = visualizer };
    if (simulationObjects.Contains(newObject))
    {
        simulationObjects.Add(newObject);
        return true;
    }
    return false;
}

但在这种情况下,我需要确保cacheHolder和visualizer不会出现在任何其他组合中。

编辑2:

我正在使用Unity3D,它主要支持.NET。 3.5

正如所指出的那样,使用比List更快的查找的.NET集合可能更好。或者如果列表是可排序的,请使用List.BinarySearch。

编辑3:

我将使用struct版本。我不确定会有多少次查找。如果它成为一个问题,我可能会改为另一个.NET集合。

3 个答案:

答案 0 :(得分:2)

Eric Lippert的评论非常正确。 在这种情况下,甚至不需要尝试比较性能差异,因为集合非常小,因此无需担心CPU时间。

内存明智...列表结构使用连续的内存块,只有当它们非常大时才会成为内存问题。 (我的意思是数百万。)

只有其他建议: 如果您要在每个游戏周期中对这些列表执行搜索,则只需选择另一个针对查找进行优化的结构。字典在检索项目时更有效,因为查找从索引执行查找,而列表将执行项目的遍历。

答案 1 :(得分:1)

我建议你使用struct方法,原因有两个:

  • 在.NET中,特殊处理结构类通用类型参数,no boxing will occur
  • 这种方法将通过结构确保您将匹配的元素组合在一起。对我而言,感觉它更容易推理。

因此,当涉及到是否使用结构列表结构列表的问题时,我当然更喜欢使用结构列表,即使它导致了性能下降很少。在您的情况下,我期望结构列表版本更好地执行,但我无法保证。您可以随时运行分析。但有一件事是肯定的:性能差异远小于AddSimulationObject中线性搜索的成本。

答案 2 :(得分:0)

您正在谈论参考文献列表,您的任何一种解决方案都可以。 但是,如果您的两个接口都是成对的,那么您可以使用 List<Tuple<ICacheHolder, IVisualizer>>