Search code examples
c#performancecomparison

Comparison via Equals or HashCode. which is faster?


I have to compare a object with the raw properties of the same class. Meaning, i have to compare those:

struct Identifier
{
    string name;
    string email;
}

with the two strings name and email. I know i could just create a new Identifier instance for name and email and pass that into equals(). My application has to be very fast and resource-saving.

I know that comparison via hashcode isn't a good way, because as explained here there are collisions. But collisions are okay for me, i just need it to be fast.

So,

1) is comparison via GetHashCode (check if the hashcode of both objects are the same) faster than Equals()?

2) Should i instead creating a new instance of Identifier of the two values for the comparison, make a new method which takes the values directly? e.g.

struct Identifier {
  string name;
  string email;

  bool Equals(string name, string email) {
      // todo comparison via hashcode or equals
  }
}

I would use the Equals() and GetHashCode() method generated by resharper.


Solution

  • Comparing hash codes could be faster if you save them on the Identifier instance (see below). However, it is not the same thing as comparing for equality.

    Comparing hash codes lets you check if two items are definitely not equal to each other: you know this when you get different hash codes.

    When hash codes are equal, however, you cannot make a definitive statement about the equality: the items could be equal or not equal to each other. That is why hash-based containers must always follow hash code comparison, direct or indirect, with a comparison for equality.

    Try implementing the comparison like this:

    struct Identifier {
        string name;
        string email;
        int nameHash;
        int emailHash;
        public Identifier(string name, string email) {
            this.name = name;
            nameHash = name.GetHashCode();
            this.email = email;
            emailHash = email.GetHashCode();
        }
        bool Equals(string name, string email) {
            return name.GetHashCode() == nameHash
                && email.GetHashCode() == emailHash
                && name.equals(this.name)
                && email.equals(this.email);
        }
    }
    

    Comparing to pre-computed hash code would short-circuit the actual equality comparison, so you could save some CPU cycles when most of the comparisons end up returning false.