集合中只允许.NET 中的唯一项?

C # 中是否有一个集合不允许您向其中添加重复项?例如,与愚蠢的类

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);

但是,是否有一个类可以同样地保证惟一性,但是没有 KeyValuePair?我认为 HashSet<T>可以做到这一点,但是通过阅读文档,似乎类只是一个集合实现(想想看)。

121327 次浏览

来自 MSDN 的 HashSet<T>页面:

HashSet (Of T)类提供了高性能的 set 操作 集合是不包含重复元素的集合,其元素没有特定的顺序。

(强调我的)

你可以试试 HashSet<T>

HashSet<T>就是你要找的。来自 MSDN(加重语气) :

HashSet<T>类提供高性能的集合操作。集合是 不包含重复的元素的集合,它的元素没有特定的顺序。

请注意,如果该项被添加到集合中,则 HashSet<T>.Add(T item)返回 bool—— true; 如果该项已经存在,则返回 false

如果您所需要的只是确保元素的唯一性,那么 HashSet 就是您所需要的。

你说的“只是一个集合实现”是什么意思?根据定义,集合是不保存元素顺序的唯一元素的集合。

我再说一句。

如果你需要抛出 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();
}
}

这可能是有用的例如,如果你需要它在许多地方..。

HashSet 上的扩展方法怎么样?

public static void AddOrThrow<T>(this HashSet<T> hash, T item)
{
if (!hash.Add(item))
throw new ValueExistingException();
}

您可以按以下方式查看某种唯一列表

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"始终当重复添加到它

作为一个整体检查不同的方法,这里有4种方法来检查集合是否有任何重复:

public static bool LinqAny<T>(IEnumerable<T> enumerable)
{
HashSet<T> set = new();


return enumerable.Any(element => !set.Add(element));
}


public static bool LinqAll<T>(IEnumerable<T> enumerable)
{
HashSet<T> set = new();


return !enumerable.All(set.Add);
}


public static bool LinqDistinct<T>(IEnumerable<T> enumerable)
{
return enumerable.Distinct().Count() != enumerable.Count();
}


public static bool ToHashSet<T>(IEnumerable<T> enumerable)
{
return enumerable.ToHashSet().Count != enumerable.Count();
}