【问题标题】:IEqualityComparer using list of string as comparerIEqualityComparer 使用字符串列表作为比较器
【发布时间】:2014-10-20 15:34:57
【问题描述】:

我正在尝试设置一个使用字符串列表作为比较属性的 IEqualityComparer。

在下面的 2 行代码中使用 except 和 Intersect 时,所有记录都被视为“新”,没有一个被识别为“旧”。

List<ExclusionRecordLite> newRecords = currentRecords.Except(historicalRecords, new ExclusionRecordLiteComparer()).ToList();
List<ExclusionRecordLite> oldRecords = currentRecords.Intersect(historicalRecords, new ExclusionRecordLiteComparer()).ToList();

这是我的 IEqualityComparer 类(单词是一个列表)

public class RecordComparer : IEqualityComparer<Record>
{
    public bool Equals(Record x, Record y)
    {
        if (object.ReferenceEquals(x, y))
            return true;

        if (x == null || y == null)
            return false;

        return x.Words.SequenceEqual(y.Words);
    }

    public int GetHashCode(Record obj)
    {
        return new { obj.Words }.GetHashCode();
    }
}

【问题讨论】:

    标签: c# iequalitycomparer


    【解决方案1】:

    您的GetHashCode 不正确。像这样使用:

    public override int GetHashCode()
    {
        if(Words == null) return 0;
        unchecked
        {
            int hash = 19;
            foreach (var word in Words)
            {
                hash = hash * 31 + (word == null ? 0 : word.GetHashCode());
            }
            return hash;
        }
    }
    

    回答为什么集合不覆盖GetHashCode,而是使用返回唯一值的object.GetHashCodeWhy does C# not implement GetHashCode for Collections?

    【讨论】:

    • 非常感谢,此设置有效。为什么hash设置为19并乘以31?
    • 因为它们是素数,可以减少碰撞的可能性。请注意,“假”碰撞并没有那么糟糕,因为它会被Equals 修复,但许多“假”碰撞效率低下。
    【解决方案2】:

    假设您将 Words 存储在 List 中,然后在其上调用 GetHashCode 不会返回其中项目的哈希值,而是返回来自 @987654324 的哈希值@。

    您需要实现自己的哈希函数,枚举单词并生成哈希值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-22
      • 2011-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-05
      相关资源
      最近更新 更多