Skip to content

Equals, HashCode, IEquatable

DUONG Phu-Hiep edited this page Oct 28, 2018 · 2 revisions

Quick theory revisit

  • 2 equal objects MUST to have the same hashCode

  • 2 objects which has the same hashCode might not be equal.

    • hashCode conflict means 2 different objects got the same hashCode
  • hashCode computation must to be very fast with minimum conflict otherwise it affect Dictionary performance

  • in C#, if we override Equals(), we usually should also override GetHashCode() and "==" base on the new Equals()

using System;

namespace multirequester.schema.interfaces
{
    public class Keyword: IEquatable<Keyword>
    {
        public string text;
        public string className;
        public string relatedTo;

        //need to implement this one
        public bool Equals(Keyword other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return text == other.text && className == other.className && relatedTo == other.relatedTo;
        }

        //need to implement this one
        public override int GetHashCode()
        {
            unchecked //Allow overflow result number
            {
                // Choose large primes to avoid hashing collisions on large number
                const int HashingBase = (int)2166136261;
                const int HashingMultiplier = 16777619;

                //use XOR for higher performence
                var hash = HashingBase;
                hash = (hash * HashingMultiplier) ^ (!Object.ReferenceEquals(null, text) ? text.GetHashCode() : 0);
                hash = (hash * HashingMultiplier) ^ (!Object.ReferenceEquals(null, className) ? className.GetHashCode() : 0);
                hash = (hash * HashingMultiplier) ^ (!Object.ReferenceEquals(null, relatedTo) ? relatedTo.GetHashCode() : 0);
                return hash;
            }
        }

        public override bool Equals(Object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != GetType()) return false;

            var other = (Keyword)obj;
            return Equals(other);
        }

        public static bool operator ==(Keyword k1, Keyword k2)
        {
            if (object.ReferenceEquals(k1, k2))
            {
                return true;
            }

            // Ensure that "numberA" isn't null
            if (object.ReferenceEquals(null, k1))
            {
                return false;
            }

            return (k1.Equals(k2));
        }

        public static bool operator !=(Keyword k1, Keyword k2)
        {
            return !(k1 == k2);
        }
    }
}