Search code examples
c#linqdistinctiequalitycomparer

Implementing IEqualityComparer<T> on an object with two properties in C#


I have a case where I need to grab a bunch of items on distinct, but my source is a collection of objects with two properties, like this:

public class SkillRequirement
{
    public string Skill { get; set; }
    public string Requirement { get; set; }
}

I try to get a collection as follows:

SkillRequirementComparer sCom = new SkillRequirementComparer();

var distinct_list = source.Distinct(sCom);

I tried to implement an IEqualityComparer<T> for this, but I fell stumped at the GetHashCode() method.

The class for the Comparer:

public class SkillRequirementComparer : IEqualityComparer<SkillRequirement>
{
    public bool Equals(SkillRequirement x, SkillRequirement y)
    {
        if (x.Skill.Equals(y.Skill) && x.Requirement.Equals(y.Requirement))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public int GetHashCode(SkillRequirement obj)
    {
        //?????
    }
}

Normally I would just use GetHashCode() on a property, but because I am comparing on two properties, I'm a bit at a loss of what to do. Am I doing anything wrong, or missing something really obvious?


Solution

  • You can implement GetHashCode in the following way:

    public int GetHashCode(SkillRequirement obj)
    {
        unchecked
        {
            int hash = 17;
            hash = hash * 23 + obj.Skill.GetHashCode();
            hash = hash * 23 + obj.Requirement.GetHashCode();
            return hash;
        }
    }
    

    originally from J.Skeet

    If the properties can be null you should avoid a NullReferenceException, e.g.:

    int hash = 17;
    hash = hash * 23 + (obj.Skill ?? "").GetHashCode();
    hash = hash * 23 + (obj.Requirement ?? "").GetHashCode();
    return hash;