You can try this implementation (source):
public sealed class OrderedSet<T> : ICollection<T>
{
private readonly IDictionary<T, LinkedListNode<T>> _dictionary;
private readonly LinkedList<T> _linkedList;
public OrderedSet()
: this(EqualityComparer<T>.Default)
{
}
private OrderedSet(IEqualityComparer<T> comparer)
{
_dictionary = new Dictionary<T, LinkedListNode<T>>(comparer);
_linkedList = new LinkedList<T>();
}
public int Count => _dictionary.Count;
public bool IsReadOnly => _dictionary.IsReadOnly;
void ICollection<T>.Add(T item)
{
Add(item);
}
public void Clear()
{
_linkedList.Clear();
_dictionary.Clear();
}
public bool Remove(T item)
{
var found = _dictionary.TryGetValue(item, out var node);
if (!found)
{
return false;
}
_dictionary.Remove(item);
_linkedList.Remove(node);
return true;
}
public IEnumerator<T> GetEnumerator()
{
return _linkedList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public bool Contains(T item)
{
return _dictionary.ContainsKey(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
_linkedList.CopyTo(array, arrayIndex);
}
public void Add(T item)
{
if (_dictionary.ContainsKey(item))
{
return;
}
var node = _linkedList.AddLast(item);
_dictionary.Add(item, node);
}
public void Reverse()
{
var head = _linkedList.First;
while (head.Next != null)
{
var next = head.Next;
_linkedList.Remove(next);
_linkedList.AddFirst(next.Value);
}
}
}
Please note that this is an OrderSet which preserves the insertion order unlike SortedSet which keeps the set sorted according to some comparator (e.g. alphabetically).
I added the Reverse() method from here.