Коллекция, которая позволяет использовать только уникальные элементы в .NET?
Есть ли коллекция на С#, которая не позволит вам добавить к ней дубликаты? Например, с глупым классом
public class Customer {
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public override int GetHashCode() {
return (FirstName + LastName + Address).GetHashCode();
}
public override bool Equals(object obj) {
Customer C = obj as Customer;
return C != null && String.Equals(this.FirstName, C.FirstName) && String.Equals(this.LastName, C.LastName) && String.Equals(this.Address, C.Address);
}
}
Следующий код (очевидно) выдаст исключение:
Customer Adam = new Customer { Address = "A", FirstName = "Adam", LastName = "" };
Customer AdamDup = new Customer { Address = "A", FirstName = "Adam", LastName = "" };
Dictionary<Customer, bool> CustomerHash = new Dictionary<Customer, bool>();
CustomerHash.Add(Adam, true);
CustomerHash.Add(AdamDup, true);
Но есть ли класс, который так же гарантирует уникальность, но без KeyValuePairs? Я думал, что HashSet<T>
сделает это, но, прочитав документы, кажется, что класс - это просто реализация набора (go figure).
Ответы
Ответ 1
HashSet<T>
- это то, что вы ищете. Из MSDN (выделено мной):
Класс HashSet<T>
обеспечивает высокопроизводительные операции набора. Набор представляет собой набор, в котором не содержит повторяющихся элементов, а элементы которого не имеют особого порядка.
Обратите внимание, что метод HashSet<T>.Add(T item)
возвращает bool
- true
, если элемент был добавлен в коллекцию; false
, если элемент уже присутствовал.
Ответ 2
Как насчет только метода расширения на HashSet?
public static void AddOrThrow<T>(this HashSet<T> hash, T item)
{
if (!hash.Add(item))
throw new ValueExistingException();
}
Ответ 3
На странице HashSet<T>
в MSDN:
Класс HashSet (Of T) обеспечивает высокопроизводительные операции набора. Набор представляет собой набор, который не содержит повторяющихся элементов и элементы которого не имеют особого порядка.
(акцент мой)
Ответ 4
Если вам нужно только обеспечить уникальность элементов, то HashSet - это то, что вам нужно.
Что вы имеете в виду, когда говорите "просто набор реализации"? Набор (по определению) представляет собой набор уникальных элементов, который не сохраняет порядок элементов.
Ответ 5
Вы можете попробовать HashSet<T>
Ответ 6
Просто чтобы добавить мои 2 цента...
если вам нужен метод ValueExistingException-throwing HashSet<T>
, вы также можете легко создать свою коллекцию:
public class ThrowingHashSet<T> : ICollection<T>
{
private HashSet<T> innerHash = new HashSet<T>();
public void Add(T item)
{
if (!innerHash.Add(item))
throw new ValueExistingException();
}
public void Clear()
{
innerHash.Clear();
}
public bool Contains(T item)
{
return innerHash.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
innerHash.CopyTo(array, arrayIndex);
}
public int Count
{
get { return innerHash.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(T item)
{
return innerHash.Remove(item);
}
public IEnumerator<T> GetEnumerator()
{
return innerHash.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
это может быть полезно, например, если вам это нужно во многих местах...
Ответ 7
Вы можете посмотреть что-то вроде уникального списка следующим образом
public class UniqueList<T>
{
public List<T> List
{
get;
private set;
}
List<T> _internalList;
public static UniqueList<T> NewList
{
get
{
return new UniqueList<T>();
}
}
private UniqueList()
{
_internalList = new List<T>();
List = new List<T>();
}
public void Add(T value)
{
List.Clear();
_internalList.Add(value);
List.AddRange(_internalList.Distinct());
//return List;
}
public void Add(params T[] values)
{
List.Clear();
_internalList.AddRange(values);
List.AddRange(_internalList.Distinct());
// return List;
}
public bool Has(T value)
{
return List.Contains(value);
}
}
и вы можете использовать его следующим образом
var uniquelist = UniqueList<string>.NewList;
uniquelist.Add("abc","def","ghi","jkl","mno");
uniquelist.Add("abc","jkl");
var _myList = uniquelist.List;
всегда будет возвращать только "abc","def","ghi","jkl","mno"
даже если к нему добавлены дубликаты