linq Except and custom IEqualityComparer

Joe picture Joe · Mar 23, 2010 · Viewed 11.5k times · Source

I'm trying to implement a custom comparer on two lists of strings and use the .Except() linq method to get those that aren't one one of the lists. The reason I'm doing a custom comparer is because I need to do a "fuzzy" compare, i.e. one string on one list could be embedded inside a string on the other list.

I've made the following comparer

public class ItemFuzzyMatchComparer : IEqualityComparer<string>
{
    bool IEqualityComparer<string>.Equals(string x, string y)
    {
        return (x.Contains(y) || y.Contains(x));
    }

    int IEqualityComparer<string>.GetHashCode(string obj)
    {
        if (Object.ReferenceEquals(obj, null))
            return 0;
        return obj.GetHashCode();
    }
}

When I debug, the only breakpoint that hits is in the GetHashCode() method. The Equals() never gets touched. Any ideas?

Answer

Jon Skeet picture Jon Skeet · Mar 23, 2010

If all the hash codes returned are different, it never needs to compare for equality.

Basically the problem is that your hash and equality concepts are very different. I'm not entirely sure how you'd correct this, but until you've done so it certainly won't work.

You need to make sure that if Equals(a, b) returns true, then GetHashCode(a) == GetHashCode(b). (The reverse doesn't have to be true - hash collisions are acceptable, although obviously you want to have as few of them as possible.)