.net 集合保持插入顺序

.net 集合保持插入顺序,.net,collections,set,.net,Collections,Set,我需要一个集合,它的行为就像集合一样,并保留元素插入的顺序 有没有一个,或者我必须自己实施 最好的实现是什么?它在.NET中不存在,但您可以使用列表和DistinctLINQ扩展方法对其进行模拟,该方法应保持底层列表的顺序是否会执行您想要的操作 虽然它不是泛型的(意味着它返回的所有内容都必须被强制转换或取消绑定),并且是一个字典(而不是集合),但它将按照您想要的方式运行。您可以轻松地使用一些任意值,如null或true作为值,并让键成为集合的成员 下面是一个可能的实现: public class

我需要一个集合,它的行为就像集合一样,并保留元素插入的顺序

有没有一个,或者我必须自己实施


最好的实现是什么?

它在.NET中不存在,但您可以使用
列表和
Distinct
LINQ扩展方法对其进行模拟,该方法应保持底层
列表的顺序
是否会执行您想要的操作

虽然它不是泛型的(意味着它返回的所有内容都必须被强制转换或取消绑定),并且是一个字典(而不是集合),但它将按照您想要的方式运行。您可以轻松地使用一些任意值,如
null
true
作为值,并让键成为集合的成员

下面是一个可能的实现:

public class OrderedSet : ICollection, IEnumerable
{
    OrderedDictionary dict = new OrderedDictionary();
    public void Add(object member)
    {
        dict.Add(member, null);
    }
    public void Clear()
    {
        dict.Clear();
    }
    public void CopyTo(Array array, int index)
    {
        for (int i = 0; i < Count; i++)
            array[i + index] = dict[i];
    }
    public bool Contains(object member)
    {
        return dict.Contains(member);
    }
    public void Insert(int index, object member)
    {
        dict.Insert(index, member, null);
    }
    public void Remove(object member)
    {
        dict.Remove(member);
    }
    public void RemoveAt(int index)
    {
        dict.RemoveAt(index);
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return dict.Keys.GetEnumerator();
    }

    public int Count { get { return dict.Count; } }
    public ICollection Members { get { return dict.Keys; } }
    bool ICollection.IsSynchronized { get { return dict.IsSynchronized; } }
    object ICollection.SyncRoot { get { return dict.SyncRoot; } }
}
公共类OrderedSet:ICollection,IEnumerable { OrderedDictionary dict=新的OrderedDictionary(); 公共无效添加(对象成员) { dict.Add(成员,空); } 公共空间清除() { 格言(Clear); } public void CopyTo(数组,int索引) { for(int i=0;i
List incontrolist=new ArrayList(); . . . Set countrySet=新的LinkedHashSet(非国家列表)


LinkedHashSet不允许复制,并保持插入顺序。

创建一个很容易:

public class InsertionOrderSet<T> : KeyedCollection<T,T>
{
    protected override T GetKeyForItem(T item)
    {
        return item;
    }
}
public类InsertionOrderSet:KeyedCollection
{
受保护的覆盖T GetKeyForItem(T项)
{
退货项目;
}
}

警告:通过
插入重复项。Add(T)
将导致
ArgumentException
s,这与
哈希集
不同,在这种情况下,哈希集只会返回
false

我意识到这是一篇老文章,但最近我需要类似的东西,如果有人想要一个通用的序列来维护添加的项目的顺序(以及允许您在任何给定项目之前和之后插入),那么这个实现可能会有所帮助。我相信有人有更有效的方法来完成这件事,但这确实奏效了

public class Sequence<T> : ICollection<T>
{
    private readonly SortedList<long, T> _baseList;

    public Sequence()
    {
        this._baseList = new SortedList<long, T>();
    }

    public IEnumerator<T> GetEnumerator()
    {
        return this._baseList.Values.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }

    public void Add(T item)
    {
        this._baseList.Add(this._baseList.Count(), item);
    }

    public void AddAfter(T item, T newItem)
    {
        var currentIndex = this._baseList.IndexOfValue(item);
        if (currentIndex == _baseList.Count())
        {
            this.Add(newItem);
        }
        else
        {
            var itemsToMove = new SortedList<long, T>();
            var total = Count;
            for (var i = currentIndex + 1; i < total; i++)
            {
                itemsToMove.Add(i, _baseList[i]);
                _baseList.Remove(i);
            }

            this.Add(newItem);
            foreach (var itemToMove in itemsToMove)
            {
                this.Add(itemToMove.Value);
            }
        }
    }

    public void AddBefore(T item, T newItem)
    {
        var currentIndex = this._baseList.IndexOfValue(item);
        var itemsToMove = new SortedList<long, T>();
        var total = Count;
        for (var i = currentIndex; i < total; i++)
        {
            itemsToMove.Add(i, this._baseList[i]);
            _baseList.Remove(i);
        }

        this.Add(newItem);
        foreach (var itemToMove in itemsToMove.Values)
        {
            this.Add(itemToMove);
        }
    }

    public void Clear()
    {
        this._baseList.Clear();
    }

    public bool Contains(T item)
    {
        return this._baseList.ContainsValue(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        this._baseList.Values.CopyTo(array, arrayIndex);
    }

    public bool Remove(T item)
    {
        try
        {
            this._baseList.RemoveAt(this._baseList.IndexOfValue(item));
            return true;
        }
        catch
        {
            return false;
        }
    }

    public int Count
    {
        get
        {
            return this._baseList.Count();
        }
    }

    public bool IsReadOnly
    {
        get
        {
            return false;
        }
    }
}
公共类序列:ICollection
{
私有只读分类列表_基本列表;
公共序列()
{
此._baseList=new SortedList();
}
公共IEnumerator GetEnumerator()
{
返回此值。_baseList.Values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
返回此.GetEnumerator();
}
公共作废新增(T项)
{
this.\u baseList.Add(this.\u baseList.Count(),item);
}
公共无效AddAfter(T项,T新项)
{
var currentIndex=此._baseList.IndexOfValue(项);
if(currentIndex==\u baseList.Count())
{
添加(新项目);
}
其他的
{
var itemsToMove=new SortedList();
var总计=计数;
对于(var i=currentIndex+1;i
这非常令人沮丧,不是吗?PowerShell中使用哈希表的字典也会丢失插入顺序。我需要快速索引,但可以承受慢速插入,因此我将求助于
List
,并将编写扩展方法
AddUnique
,以实现集合语义。LINQ的
Distinct
确实保留了当前实现的顺序,但政府明确表示,这是无序的。小心进行。这会起作用,但他基本上只能使用键,不能使用值。不太理想,但它能完成任务。这样的收集工作怎么办?如果您插入一个元素作为第一个元素,然后在20次迭代后再次插入它,它应该是元素1还是元素20?对于我的任务,我需要它是元素1。