Если ваш вариант использования подразумевает, что элементы в коллекции должны быть уникальными, то вам следует использовать структуру данных, которая обеспечивает это.
Делая это, вы не только избегаете написания метода поиска O (N) для проверки на наличие дубликатов, но также можете создать пузырек для ранее существовавшего исключения дубликата, которое будет генерировать коллекция такого рода. *
Однако .NET не имеет отдельной коллекции, которая сохраняет порядок сортировки, хотя очень просто расширить List для поддержки этого.
Подход, который я использовал ниже, жертвует объемом памяти для скорости, сохраняя уникальные значения во втором HashSet. Если бы объем памяти был более важным, вам просто нужно было бы проверять O (N) при каждой операции добавления. Поскольку методы не являются виртуальными (по некоторым причинам) в List, я привел к сокрытию базовых методов с помощью ключевого слова new.
Обратите внимание, что это всего лишь пример, и он не является потокобезопасным, и, вероятно, его не следует использовать в реальном производственном приложении.
public class UniqueList<T> : List<T>
{
private HashSet<T> _internalHash = new HashSet<T>();
public UniqueList() : base() { }
public UniqueList(IEnumerable<T> collection) : base(collection) { }
public UniqueList(int capacity) : base(capacity) { }
public new void Add(T item)
{
if (!_internalHash.Add(item))
throw new ArgumentException("Item already exists in UniqueList");
base.Add(item);
}
public new void AddRange(IEnumerable<T> collection)
{
foreach (T t in collection)
{
this.Add(t);
}
}
public new bool Remove(T item)
{
_internalHash.Remove(item);
return base.Remove(item);
}
public new int RemoveAll(Predicate<T> match)
{
int removedElems = 0;
foreach (T item in this)
{
if (match(item))
{
this.Remove(item);
removedElems++;
}
}
return removedElems;
}
public new void RemoveAt(int index)
{
this.Remove(this[index]);
}
public new void RemoveRange(int index, int count)
{
for (int i = index; i < count; i++)
{
this.Remove(this[i]);
}
}
}