Вы не можете избежать повтора в List. Ни в коем случае - проверка предметов не производится.
Если вы не беспокоитесь о порядке вещей - используйте HashSet.
Если вы хотите сохранить порядок предметов (на самом деле есть небольшая двусмысленность - должен появиться элемент с индексом первого сложения или по индексу последнего добавления). Но вы хотите быть уверены, что все элементы уникальны, тогда вы должны написать свой собственный класс List. То есть то, который реализует интерфейс IList<T>
:
public class ListWithoutDuplicates<T> : IList<T>
И у вас есть различные варианты здесь. Например. вы должны решить, что для вас важнее - быстрое добавление или потребление памяти. Поскольку для быстрого добавления и содержит операцию, вы должны использовать некоторую структуру данных на основе хэша. Что неупорядочено. Вот пример реализации с HashSet для хранения хэшей всех элементов, хранящихся во внутреннем списке. Вам нужно будет следующие поля:
private readonly HashSet<int> hashes = new HashSet<int>();
private readonly List<T> items = new List<T>();
private static readonly Comparer<T> comparer = Comparer<T>.Default;
Добавление элементов просто (предупреждение: не нулевые чеки здесь и далее) - не использовать элемент хэш-код для быстрого O (1) проверить, если он уже добавлен. Используйте тот же подход для удаления элементов:
public void Add(T item)
{
var hash = item.GetHashCode();
if (hashes.Contains(hash))
return;
hashes.Add(hash);
items.Add(item);
}
public bool Remove(T item)
{
var hash = item.GetHashCode();
if (!hashes.Contains(hash))
return false;
hashes.Remove(item.GetHashCode());
return items.Remove(item);
}
Некоторые индексные на основе операций:
public int IndexOf(T item)
{
var hash = item.GetHashCode();
if (!hashes.Contains(hash))
return -1;
return items.IndexOf(item);
}
public void Insert(int index, T item)
{
var itemAtIndex = items[index];
if (comparer.Compare(item, itemAtIndex) == 0)
return;
var hash = item.GetHashCode();
if (!hashes.Contains(hash))
{
hashes.Remove(itemAtIndex.GetHashCode());
items[index] = item;
hashes.Add(hash);
return;
}
throw new ArgumentException("Cannot add duplicate item");
}
public void RemoveAt(int index)
{
var item = items[index];
hashes.Remove(item.GetHashCode());
items.RemoveAt(index);
}
И доели:
public T this[int index]
{
get { return items[index]; }
set { Insert(index, value); }
}
public int Count => items.Count;
public bool Contains(T item) => hashes.Contains(item.GetHashCode());
public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => items.GetEnumerator();
Вот и все. Теперь у вас есть реализация списка, которая будет добавлять элемент только один раз (первый раз). Например.
var list = new ListWithoutDuplicates<int> { 1, 2, 1, 3, 5, 2, 5, 3, 4 };
Будет ли создать список с пунктами 1, 2, 3, 5, 4. Примечание: если потребление памяти является более важным, чем производительность, то вместо того, чтобы использовать хеши использовать items.Contains
операцию, которая является О (п).
КСТАТИ Что мы только что сделали это на самом деле IList Decorator
Использование 'HashSet' он не разрушает ваш performance.Check этот http://stackoverflow.com/questions/4558754/define-what-is-a -hashset – Prabu
Существуют и другие альтернативы, но в зависимости от размера ваших предметов они могут оказаться непригодными. «HashSet» лучше, потому что он удаляет дубликаты и гарантирует «O (1)» «Добавить» и «Содержит». Но вы также можете добавить элементы в список, а затем использовать 'Distinct(). ToList()' используя LINQ. Это зависит от вашего варианта использования. – jorgonor
_ «Но я знаю, что хешсет менее эффективен». Это неправильно. Это просто не список, поэтому он не обеспечивает доступ через индекс. Кроме того, это очень эффективно –