如何获得列表的唯一id ?

本文关键字:id 唯一 何获得 列表 | 更新日期: 2023-09-27 18:02:58

我有一个List<T>,其中T是一个对id具有int字段的类。如何获得一个没有在List<T>中的任何对象中使用的唯一id值的最佳方法?

这个过程通常是如何编码的?是否有一种数据类型可以帮助实现这一点,或者我需要存储最大的id值?

编辑

如果我得到一个id为1的对象。然后从List中删除该对象。当我创建一个新对象时,我希望唯一id为2。在这种情况下,还有比存储最后一个唯一id更好的方法吗?

谢谢。

如何获得列表的唯一id ?

对于这种方法,我将编写list 的继承类来保存逻辑,因此您不需要在访问列表的任何地方实现它。如果你有一个带有Id值的最小接口,你甚至可以让它保持泛型。

interface IWithId {
    int Id { get; set; }
}
class CustomList<T> : List<T> where T : class, IWithId {
    private lastUsedId = 1;
    public void AddObjectWithAutomaticId(T newObject) {
        newObject.Id = lastUsedId++;
        base.Add(newObject);
    }
    public T GetElementById(int id) {
         return base.SingleOrDefault(p => p.Id == id);
    }
}

Remove方法仍然可以像以前一样工作。该类存储最后使用的Id,与您删除的内容无关。当您想要添加具有给定Id的对象而不自动填充它时,Add方法也仍然可用。

我同意GUID适合作为id属性的评论。但是,如果需要使用int类型,那么我建议创建一个新类。

继承List<T>的问题是,您必须重写多个方法,以确保Add(), AddRange(), Insert()等不能添加重复的id和更新存储的最大id。很容易漏掉一个。

我将使用一个不继承任何东西,但在内部使用字典的类。这将不会有所有相同的方法作为List<T>,但这并不一定是一件坏事-它节省了错误,你可以有一个ToList()方法,当他们想要查询它,如果它是List<T>

使用前面答案的一部分来确保T具有Id属性,给出:

interface IHasId {
    int Id { get; set; }
}
class AutoIdList<T> where T : class, IHasId {
    private readonly IDictionary<int, T> _dictionary = new Dictionary<int, T>();
    //Using this list ensures you don't duplicate ids even
    //for an item added with an explicit id then removed
    private IList<int> _historicalIds = new List<int>();
    private int highestAutoGeneratedId = 0;
    public List<T> ToList() {
        return _dictionary.Values.ToList();
    }
    public void Add(T item, bool generateId) {
        if (generateId) {
            highestAutoGeneratedId = NextId();
            T.Id = highestAutoGeneratedId;
        }
        Add(T);
    }
    public void Replace(T item) {
        _dictionary[item.Id] = item;
    }
    public void Remove(T item) {
        _dictionary.Remove(item.Id);
    }
    private void Add(T item) {
        if (_historicalIds.Contains(T.Id)) {
            //throw an appropriate exception
        } else {
            _historicalIds.Add(T.Id);
            _dictionary.Add(T.Id, T);
        }
    }
    private int NextId() {
        var id = highestAutoGeneratedId + 1;
        while (_historicalIds.Contains(id)) {
            id++;
        }
        return id;
    }
    //More methods to simulate AddRange, Insert, etc if required. Leave if not.
    //Should all have simple logic but require checking of Id if adding anything
    //Also need logic to maintain the list of used ids
}