C# 在.NET中仅允许唯一项的集合?

C# 在.NET中仅允许唯一项的集合?,c#,set,hashset,C#,Set,Hashset,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 + Last

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);
Customer Adam=新客户{Address=“A”,FirstName=“Adam”,LastName=“”};
客户AdamDup=新客户{Address=“A”,FirstName=“Adam”,LastName=“”};
Dictionary CustomerHash=新字典();
CustomerHash.Add(Adam,true);
CustomerHash.Add(AdamDup,true);
但是是否有一个类可以同样保证唯一性,但没有KeyValuePairs?我以为
HashSet
可以做到这一点,但阅读了文档后,类似乎只是一个集合实现(见图)。

来自MSDN页面:

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

(我的重点)

你可以试试看

HashSet
就是你要找的。起自(加强调):

HashSet
类提供了高性能的集合操作。集合是一个集合,不包含重复的元素,并且其元素没有特定的顺序


请注意,如果项目已添加到集合中,则返回
bool
--
true
false
如果项目已经存在。

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


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

只需添加我的2美分

如果需要ValueExistingException抛出
哈希集
,也可以轻松创建集合:

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();
    }
}
公共类throwinghasset:ICollection
{
私有HashSet innerHash=新HashSet();
公共作废新增(T项)
{
如果(!innerHash.Add(项))
抛出新值existingexception();
}
公共空间清除()
{
innerHash.Clear();
}
公共布尔包含(T项)
{
返回innerHash.Contains(项);
}
public void CopyTo(T[]数组,int arrayIndex)
{
CopyTo(数组,arrayIndex);
}
公共整数计数
{
获取{return innerHash.Count;}
}
公共图书馆是只读的
{
获取{return false;}
}
公共布尔删除(T项)
{
返回innerHash.Remove(项);
}
公共IEnumerator GetEnumerator()
{
返回innerHash.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
返回此.GetEnumerator();
}
}

例如,如果您在许多地方需要它,这可能会很有用…

仅在HashSet上使用一个扩展方法如何

public static void AddOrThrow<T>(this HashSet<T> hash, T item)
{
    if (!hash.Add(item))
        throw new ValueExistingException();
}
publicstaticvoidaddorthrow(此哈希集散列,T项)
{
如果(!hash.Add(项))
抛出新值existingexception();
}

您可以查看以下某种独特的列表

公共类唯一列表
{
公开名单
{
得到;
私人设置;
}
列表_内部列表;
公共静态唯一列表NewList
{
得到
{
返回新的唯一列表();
}
}
私人唯一名单()
{            
_internalList=新列表();
列表=新列表();
}
公共无效添加(T值)
{
List.Clear();
_添加(值);
AddRange(_internalList.Distinct());
//退货清单;
}
公共void Add(参数T[]值)
{
List.Clear();
_internalList.AddRange(值);
AddRange(_internalList.Distinct());
//退货清单;
}
公共bool Has(T值)
{
返回列表。包含(值);
}
}
你可以像下面那样使用它

var uniquelist = UniqueList<string>.NewList;
uniquelist.Add("abc","def","ghi","jkl","mno");
uniquelist.Add("abc","jkl");
var _myList = uniquelist.List;
var uniquelist=uniquelist.NewList;
唯一列表。添加(“abc”、“def”、“ghi”、“jkl”、“mno”);
唯一列表。添加(“abc”、“jkl”);
var\u myList=uniquelist.List;

即使添加了重复项,也只会始终返回
“abc”、“def”、“ghi”、“jkl”、“mno”
,我不理解您的
哈希集问题。MSDN说“HashSet类提供了高性能的集合操作。集合是一个集合,不包含重复的元素,并且其元素没有特定的顺序。”你能解释一下为什么
HashSet
不够用吗?@mootinator:
Dictionary
类不能保证任何顺序。我想他只是想在你尝试添加现有值时抛出一个异常。。。为此,只需检查从
HashSet.Add
方法返回的bool值,并在
false
时抛出。强烈建议只重载不可变类型的bool值。一个可变的客户通常会更公平地使用默认的引用等式;这个问题有点愚蠢。基本上,我一直在寻找在添加重复项时会抛出异常的东西(如Dictionary),但正如前面提到的,HashSet在添加重复项时返回false+谢谢,当然可以。我想知道是否有内置的东西,但在此情况下,感谢您+1T项应该实现IEquatable接口。如果类不继承此接口,HashSet将添加重复元素。或者,您可以将
EqualityComparer
实例的(自定义)实现传递给
HashSet
构造函数,而不是实现
IEquatable
的项。