Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IEqualityComparer using list of string as comparer

I'm attempting to setup an IEqualityComparer that uses a list of string as the comparing property.

When using Except and Intersect in the 2 lines of code below, all records are seen as 'new' and none are recognized as 'old'.

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

This is my IEqualityComparer class (Words is a List)

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();
    }
}
like image 637
mrb398 Avatar asked Mar 18 '23 03:03

mrb398


1 Answers

Your GetHashCode is incorrect. Use one like this:

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

To answer why a collection does not override GetHashCode but uses object.GetHashCode which returns a unique value: Why does C# not implement GetHashCode for Collections?

like image 113
Tim Schmelter Avatar answered Apr 02 '23 20:04

Tim Schmelter