C# 在c中从列表或哈希集中删除重复项#

C# 在c中从列表或哈希集中删除重复项#,c#,list,hashset,duplicate-removal,C#,List,Hashset,Duplicate Removal,我有一个非常简单的测试方法,它返回一个包含大量重复项的列表,但是如果没有,我想我会尝试HashSet,因为它应该删除重复项,但是我似乎需要覆盖Equals和GetHashCode,但我真的很难理解我需要做什么。请给我一些指点 HashSet<object> test = XmlManager.PeriodHashSet(Server.MapPath("../Xml/XmlFile.xml")); foreach (Object period in test2) { Perio

我有一个非常简单的测试方法,它返回一个包含大量重复项的列表,但是如果没有,我想我会尝试HashSet,因为它应该删除重复项,但是我似乎需要覆盖Equals和GetHashCode,但我真的很难理解我需要做什么。请给我一些指点

HashSet<object> test = XmlManager.PeriodHashSet(Server.MapPath("../Xml/XmlFile.xml"));
foreach (Object period in test2)
{
    PeriodData pd = period as PeriodData;
    Response.Write(pd.PeriodName + "<br>");
}
它是返回的PeriodName,我想删除它的副本。

您必须实现它才能使Distinct()工作

如果您不知道,框架如何知道如何说“这两个对象是相同的”?您必须为框架提供一种比较对象的方法,这是
IEquatable
实现的目的。

要使
HashSet
工作,您至少需要覆盖
对象.Equals
对象.GetHashCode
。这使哈希算法能够知道是什么使两个对象在值上“不同”或相同

在简化和改进代码方面,我建议进行两项主要更改以实现这一目标:

首先,您应该使用
HashSet
(或
List
),而不是
HashSet


其次,您的
PeriodData
类应该实现,以便提供适当的散列和相等。

您必须决定是什么使两个周期相等。如果要使两个时段相等,所有三个属性必须相同,则可以实现相等,因此:

public override bool Equals(object obj)
{
    if (ReferenceEquals(null, obj)) return false;
    if (ReferenceEquals(this, obj)) return true;
    if (obj.GetType() != this.GetType()) return false;
    PeriodData other = (PeriodData)obj;
    return m_StartYear == other.m_StartYear && m_EndYear == other.m_EndYear && string.Equals(m_PeriodName, other.m_PeriodName);
}
对于GetHashCode,可以执行以下操作:

    public override int GetHashCode()
    {
        return (((m_StartYear * 397) ^ m_EndYear) * 397) ^ m_PeriodName.GetHashCode();
    }
(应归功于:这些代码是根据ReSharper的代码生成工具生成的代码改编的。)

正如其他人所指出的,最好也实现
IEquatable


如果您无法修改该类,或者您不想修改它,您可以将相等比较逻辑放在另一个实现
iequalitycomparese的类中。这个堆栈流问题为您提供了一个在对象列表上进行不同排序的选项。但实际上,虽然您提出的建议可以改进代码,但问题可以通过重写Equals和GetHashCode来解决,无需更改类型参数,也无需实现
IEquatable
。我同意改进的观点,但我不理解的是重写和如何编写它们。谢谢@ReedCopsey,我接受了你和其他人的观点,并使它工作起来。重写Equals和GetHashCode可以解决这个问题。实现
IEquatable
是一个好主意,但它不是必需的。这很好,它起作用了。我只需要检查PeriodName是否相等,并根据需要进行修改。我还没有实现IEquitable,因为作为一个相对愚蠢的程序员,这对我来说更难理解。我还没有找到一个简单的解释,所以我现在就不谈了。
public override bool Equals(object obj)
{
    if (ReferenceEquals(null, obj)) return false;
    if (ReferenceEquals(this, obj)) return true;
    if (obj.GetType() != this.GetType()) return false;
    PeriodData other = (PeriodData)obj;
    return m_StartYear == other.m_StartYear && m_EndYear == other.m_EndYear && string.Equals(m_PeriodName, other.m_PeriodName);
}
    public override int GetHashCode()
    {
        return (((m_StartYear * 397) ^ m_EndYear) * 397) ^ m_PeriodName.GetHashCode();
    }