检查列表中已删除的插槽

时间:2018-12-02 17:08:38

标签: c#

我想生成一些带有ID的ItemsItem只是一个具有ID整数属性的类。创建它们后,应将它们添加到列表中。所以我有一堂课来管理所有项目

internal static class ItemPool
{
    public static readonly List<Item> items = new List<Item>(); // Store all the items here

    public static Item CreateItem()
    {
        int itemId = items.Count; // Just take the next free slot index
        Item itemToCreate = new Item(itemId);
        items.Add(itemToCreate);
        return itemToCreate;
    }

    public static void DestroyItem(int itemId)
    {
        activeItems.RemoveAt(itemId);
    }
}

现在我可以创建一些物品

Item firstItem = ItemPool.CreateItem(); // generates item with ID 0

Item secondItem = ItemPool.CreateItem(); // generates item with ID 1

ItemPool.DestroyItem(firstItem.id); // Recudes the list count to 1

Item thirdItem = ItemPool.CreateItem(); // generates item with ID 1 - ERROR

不允许第三项具有ID 1,因为项2已经具有ID。

更改代码时会出现两个问题:

如何管理此列表中的项目的ID,以使它们都不具有相同的ID?

public static Item CreateItem()
{
    int itemId = temporaryUniqueId; // create a temporary unique ID
    // ... other code
}

有什么比去做更优化的方法

public static void DestroyItem(int itemId)
{
    activeItems = activeItems.Where(item => item.id != itemId).ToList();
}

我知道我能做

public static void DestroyItem(Item item)
{
    activeItems.Remove(item);
}

但是我认为通过ID删除更为安全。我之所以这么问,是因为在这种情况下,性能就是一切

ID不必为整数值

1 个答案:

答案 0 :(得分:2)

由于ID不必为整数,因此一种方法是使用GUID作为唯一标识符,以避免必须处理潜在的冲突。

public class Item 
{
    public Guid Id { get; }

    public Item()
    {
        Id = Guid.NewGuid();
    }
}

然后,您的ItemPool类可以更改为使用ConcurrentDictionary(以避免任何竞争条件):

internal sealed class ItemPool
{
    private readonly ConcurrentDictionary<Guid, Item> items = new ConcurrentDictionary<Guid, Item>(); // Store all the items here

    public Item CreateItem()
    {
        Item itemToCreate = new Item();
        items.TryAdd(itemToCreate.Id, itemToCreate);
        return itemToCreate;
    }

    public void DestroyItem(Guid itemId)
    {
        activeItems.TryRemove(itemId, out Item _);
    }
}

我自由地删除了类的静态参数,以使其更易于测试。我还将items字段设为私有,以实现更好的封装。您不希望其他任何人绕过ItemPool并开始自己操纵集合:)