Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to write a hash code function for an comparer that matches many-to-many?

Can I write a hash code function for the following comparer logic?

Two instances of My are equal if at least two properites from (A, B, C) match.

The Equals part is simple, but I'm stumped on the hash code part, and part of me is thinking it might not be possible.

class MyOtherComparer : IEqualityComparer<My>
{
    public bool Equals(My x, My y)
    {
        if (Object.ReferenceEquals(x, y)) 
            return true;      

        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) 
            return false;

        int matches = 0;

        if(x.A == y.A) matches++;

        if(x.B == y.B) matches++;

        if(x.C == y.C) matches++;

        // match on two out of three
        return  (matches > 1)
    }

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects.
    public int GetHashCode(My x)
    {
       // ???
    }
}

UPDATE: In addition to the correct answer by Reed Copsey, a very important point about the general usefulness of a fuzzy comparer is clearly stated by Ethan Brown - please see his answer as well for a full understanding of what underlies this Question/Answer.

like image 677
Aaron Anodide Avatar asked Jun 04 '12 17:06

Aaron Anodide


People also ask

Is hashcode always the same?

hashCode() method returns the hash code for the Method class object. The hashcode returned is computed by exclusive-or operation on the hashcodes for the method's declaring class name and the method's name. The hashcode is always the same if the object doesn't change.

What are hash codes used for?

Hashing means using some function or algorithm to map object data to some representative integer value. This so-called hash code (or simply hash) can then be used as a way to narrow down our search when looking for the item in the map.


2 Answers

Yes, it's possible. The simplest implementation would be to always return a constant.

public int GetHashCode(My x) 
{ 
   return 0;
}

The GetHashCode documentation states:

Implementations are required to ensure that if the Equals method returns true for two objects x and y, then the value returned by the GetHashCode method for x must equal the value returned for y.

However, you are perfectly free to return the same hash code for two objects which are not equal, as well.

That being said, this will potentially cause some algorithms to perform very poorly, as you'll get lots of hash collisions. However, given the nature of your odd/unique equality check, this may be required.


Note that this is going to be problematic in any case. Given your logic, it's possible to have three objects, where comparer.Equals(foo, bar)==true and comparer.Equals(foo, baz)==true but comparer.Equals(baz, bar)==false. This is likely to be problematic in many cases where IEqualityComparer<T> is used.

like image 147
Reed Copsey Avatar answered Oct 14 '22 17:10

Reed Copsey


A hash code has to be the same for two equal objects, but it does not have to be different for two different objects. You could return the same value for all objects to satisfy the IEqualityComparer consumers, but there's no way I know of to get any speed benefits from the hash in your situation.

like image 42
C.Evenhuis Avatar answered Oct 14 '22 17:10

C.Evenhuis